Mock in C# with NSubstitute and FakeItEasy

In this post, rather than focusing on one specific library, what I will do is compare multiple libraries that allow us to create mocks in C#.

We already saw in another post what the difference between mock, double, and fake is. So, if you’re not familiar with these terms, I recommend starting with that post.

 

Note: due to recent changes (version 4.20) in the moq library, we won’t cover it in this post. However, you have a post dedicated to it from March 2020.

In this post, we’re going to cover mocking in .NET with the NSubstitute and FakeItEasy libraries. The goal of this post is to serve as an introduction to these libraries, or, if your boss is making you migrate from moq, help you see the syntax for the most common examples.

 

 

Remember that all the code is available on GitHub.

 

1 - What is a mock and why use it?

In this post we will explain a very common feature found in unit testing. It’s about simulating interfaces that connect with external data or third-party services. This process allows us to run thorough tests on our procedures.

 

The term "mock" technically carries a sense of imitation. Therefore, in this article, we're going to see how to imitate these interfaces that provide data access, enabling us to evaluate the program flow in detail.

Using mocks makes life easier when it comes to covering all the possible scenarios in our application.

 

For this post, we’ll show all the examples using both the NSubstitute and FakeItEasy libraries.

 

2 - Use case and popular libraries to do mocking

To see how to use mocks in C#, let’s check the following use case: a service with two dependencies. We don’t really care what those dependencies do, since we’re going to simulate their behavior.

public class ArticleService
{
    private readonly IAuthorRepository _authorRepository;
    private readonly IArticleRepository _articleRepository;

    public ArticleService(IAuthorRepository authorRepository, IArticleRepository articleRepository)
    {
        _authorRepository = authorRepository;
        _articleRepository = articleRepository;
    }

    public Article InsertArticle(string content, string title, int authorId)
    {
        if (!_authorRepository.IsValid(authorId))
        {
            throw new Exception("Author not valid");
        }
            
            
        int aritcleId = _articleRepository.Insert(content, title, authorId);

        return GetArticle(aritcleId);
    }

    public Article GetArticle(int id)
    {
        return _articleRepository.Get(id);
    }
}


public interface IAuthorRepository
{
    Author Get(int id);
    bool IsValid(int id);
}
public interface IArticleRepository
{
    int Insert(string content, string title, int authorId);
    Article Get(int id);
}

public record Article(int Id, string Content, string Title, DateOnly Date, int AuthorId);

public record Author(int Id, string Name);

And to simulate the behavior, we install the NSubstitute or FakeItEasy library. As I mentioned earlier, I have a post dedicated to the moq library.

 

 

3 - Using mocks with NSubstitute and FakeItEasy

The main use case for mock libraries is to simulate the behavior of interfaces that abstract dependencies.

 

In our example code, the interfaces refer to two repositories.

For the first example, let’s imitate and override the behavior of the Get method inside IArticlerepository:

Example with FakeItEasy:

[Fact]
public void WhenArticleExist_ThenReturnArticle() //FakeIt easy
{
    Article article = new Article(1, "content", "title", DateOnly.FromDateTime(DateTime.UtcNow), 1);
    
    IAuthorRepository authorRepository = A.Fake<IAuthorRepository>();
    IArticleRepository articleRepository = A.Fake<IArticleRepository>();
    A.CallTo(() => articleRepository.Get(article.Id)).Returns(article);
    
    ArticleService service = new ArticleService(authorRepository, articleRepository);
    Article result = service.GetArticle(article.Id);

    Assert.Equal(article.Content, result.Content);
}

As we can see, it’s straightforward. We simply use A as the type (not sure why they used A instead of Fake) and then have access to everything we need inside A.

Finally, we just have to pass our interface to the constructor.

Using A.CallTo lets us specify the behavior of the method we want to imitate.

  • Note: if it was an async method, the return should be A.CallTo(() => articleRepository.Get(article.Id)).Returns(Task.FromResult(article));.

 

Example with NSubstitute:

[Fact]
public void WhenArticleExist_ThenReturnArticle() //Nsubstitute
{
    Article article = new Article(1, "content", "title", DateOnly.FromDateTime(DateTime.UtcNow), 1);

    IAuthorRepository authorRepository = Substitute.For<IAuthorRepository>();
    IArticleRepository articleRepository = Substitute.For<IArticleRepository>();
    articleRepository.Get(article.Id).Returns(article);
    
    ArticleService service = new ArticleService(authorRepository, articleRepository);
    Article result = service.GetArticle(article.Id);

    Assert.Equal(article.Content, result.Content);
}

Very similar to the previous case, we only need to tweak the syntax a little.

Something I really like about NSubstitute is that when you mock a method, you only need to provide the corresponding values to that method, with no extra syntax.

 

3.1 - Complete mock example with NSubstitute and FakeItEasy

Now let’s move on to a more complete example, where there’s more information to validate. In this case, we will test the InsertArticle method, which has two possible outcomes, so we need to write two tests, one for each outcome.

 

As a general rule, I like to start with the happy path, so that’s what we’ll do.

 

This is the example using FakeItEasy:

[Fact]
public void WhenAuthorIsValid_ThenArticleIsInserted()
{
    Article article = new Article(1, "content", "title", DateOnly.FromDateTime(DateTime.UtcNow), 10);

    IAuthorRepository authorRepository = A.Fake<IAuthorRepository>();
    IArticleRepository articleRepository = A.Fake<IArticleRepository>();
    A.CallTo(() => authorRepository.IsValid(A<int>._)).Returns(true);
    A.CallTo(() => articleRepository.Insert(article.Content, article.Title, article.AuthorId)).Returns(article.Id);
    A.CallTo(() => articleRepository.Get(article.Id)).Returns(article);

    ArticleService service = new ArticleService(authorRepository, articleRepository);
    Article result = service.InsertArticle(article.Content, article.Title, article.AuthorId);

    A.CallTo(() => articleRepository.Insert(article.Content, article.Title, article.AuthorId))
        .MustHaveHappened(1, Times.Exactly);
    Assert.Equal(article.Content, result.Content);
}

In this example, you can see that we just added a bit more configuration for our test, but also verified that we're making the call in the assertion. For this, we use the MustHaveHappened method with the number of times we want to ensure something happens.

 

Example with NSubstitute:

[Fact]
public void WhenAuthorIsValid_ThenArticleIsInserted()
{
    Article article = new Article(1, "content", "title", DateOnly.FromDateTime(DateTime.UtcNow), 10);

    IAuthorRepository authorRepository = Substitute.For<IAuthorRepository>();
    IArticleRepository articleRepository = Substitute.For<IArticleRepository>();
    articleRepository.Get(article.Id).Returns(article);
    authorRepository.IsValid(Arg.Any<int>()).Returns(true);
    articleRepository.Insert(article.Content, article.Title, article.AuthorId).Returns(article.Id);

    ArticleService service = new ArticleService(authorRepository, articleRepository);
    Article result = service.InsertArticle(article.Content, article.Title, article.AuthorId);

    articleRepository.Received(1).Insert(article.Content, article.Title, article.AuthorId);
    Assert.Equal(article.Content, result.Content);
}

Just like before, the changes are minimal. This time we configure the number of times we’ve received a call with Received(times).

It’s very important to check the number of times a method is called to ensure we don’t have any bugs and that things work as expected.

 

 

Oh, one thing to keep in mind: when you want a method to return something but don’t care about the input, you can configure the mock to allow for that. If you look at the previous examples, you’ll see this functionality. In FakeItEasy, we use A<T>._, while in NSubstitute we use Arg.Any<T>().

 

To test the failure path where an exception is thrown, you need to do it either with your test library or as shown in the previous post with FluentAssertions.

This post was translated from Spanish. You can see the original one here.
If there is any problem you can add a comment bellow or contact me in the website's contact form

Uso del bloqueador de anuncios adblock

Hola!

Primero de todo bienvenido a la web de NetMentor donde podrás aprender programación en C# y .NET desde un nivel de principiante hasta más avanzado.


Yo entiendo que utilices un bloqueador de anuncios como AdBlock, Ublock o el propio navegador Brave. Pero te tengo que pedir por favor que desactives el bloqueador para esta web.


Intento personalmente no poner mucha publicidad, la justa para pagar el servidor y por supuesto que no sea intrusiva; Si pese a ello piensas que es intrusiva siempre me puedes escribir por privado o por Twitter a @NetMentorTW.


Si ya lo has desactivado, por favor recarga la página.


Un saludo y muchas gracias por tu colaboración

© copyright 2025 NetMentor | Todos los derechos reservados | RSS Feed

Buy me a coffee Invitame a un café