In this article, we are going to learn how to mock asynchronous methods using Moq.

Moq is an easy-to-use and most popular framework to mock tests using .NET.

To download the source code for this article, you can visit our GitHub repository.

Let’s start it.

The Repository Project We Are Going to Test

This project MockAsynchrounousMethods.Repository represents a Repository Pattern that connects our source code with a fake database.

Since the repository creation is not this article’s main goal, we are not going to show all the classes and interfaces, but the main class that we are going to test. That said, let’s inspect the ArticleRepository class:

public class ArticleRepository : IArticleRepository
{
    private readonly IFakeDbArticles _fakeDbArticle;

    public ArticleRepository(IFakeDbArticles fakeDbArticle)
    {
        _fakeDbArticle = fakeDbArticle;
    }

    public async Task<ArticleDbModel?> GetArticleAsync(int id)
    {
        return await _fakeDbArticle.GetByIdAsync(id);
    }

    public async Task<IEnumerable<ArticleDbModel>> GetAllArticlesAsync()
    {
        return await _fakeDbArticle.GetAsync();
    }
}

This class implements the IArticleRepository interface. Note that all these methods are asynchronous, and they simply retrieve data from the FakeDbArticles class:

public class FakeDbArticles : List<ArticleDbModel>, IFakeDbArticles
{
    private readonly static List<ArticleDbModel> _articles = Populate();

    private static List<ArticleDbModel> Populate()
    {
        var result = new List<ArticleDbModel>()
        {
            new ArticleDbModel
            {
                Id = 1,
                Title = "First Article",
                LastUpdate = DateTime.Now
            },
           ...
        };

        return result;
    }

    public async Task<IEnumerable<ArticleDbModel>> GetAsync()
    {
        return await Task.FromResult(_articles);
    }

    public async Task<ArticleDbModel?> GetByIdAsync(int id)
    {
        return await Task.FromResult(_articles.FirstOrDefault(x => x.Id == id));
    }
}

For further details, you can check the full implementation of this Repository in this article’s source code.

XUnit Test Project to Mock Asynchoronus Methods

Now that the repository is ready, let’s create MockAsynchronousMethods.Tests XUnit Test Project.

Once the project is ready, let’s add the MockAsynchronousMethods.Repository as a reference by right-clicking in the dependencies and then Add Project Reference.

For the next step, we need to install the Moq Framework:

Install-Package Moq

Once it is done, let’s create a Mock folder, and, inside it, aFakeDbArticleMock class that inherits from Mock<IFakeDbArticles>.

public class FakeDbArticleMock : Mock<IFakeDbArticles>
{
}

And a FakeDb class to hold a list with some articles:

public static class FakeDb
{
    public static List<ArticleDbModel> Articles = new List<ArticleDbModel>()
    {
        new ArticleDbModel
        {
            Id = 1,
            Title = "First Article",
            LastUpdate = DateTime.Now
        },
        new ArticleDbModel
        {
            Id = 2,
            Title = "Second title",
            LastUpdate = DateTime.Now
        },
        new ArticleDbModel
        {
            Id = 3,
            Title = "Third title",
            LastUpdate = DateTime.Now
        }
    };
}

Now, let’s start the setup of our mocks:

public FakeDbArticleMock GetByIdAsync()
{
    Setup(x => x.GetByIdAsync(It.IsAny<int>()))
        .ReturnsAsync(FakeDb.Articles.First());

    return this;
}

In this method, we set up an asynchronous mock call to the GetByIdAsync method from the IFakeDbArticle interface. This method returns the first article from the list we created inside the FakeDb class.

When we mock an asynchronous method, instead of using a standard Return(...) method, we use the ReturnAsync(...) method, which makes our mock asynchronous.

It is good to mention that, the ReturnAsync was introduced in version 4.5.28. In the previous versions of the Moq Framework, it was a bit different:

Setup(x => x.GetByIdAsync(It.IsAny<int>()))
    .Returns(Task.FromResult<ArticleDbModel?>(articleDbModel));

You can check the other mock methods in the full FakeDbArticleMock class implementation here.

Now that all mocks are ready, it is time to test our code.

At the root of the test project, let’s create an ArticleRepositoryTest class, responsible for holding every test method of this article. 

And then, let’s create a test method:

[Fact]
public async Task GivenAMockedDatabase_WhenRequestingAnExistingArticleAsynchronously_ThenReturnASingleArticle()
{   
    var mockArticleRepository = new FakeDbArticleMock()
        .GetByIdAsync();

    var articleRepository = new ArticleRepository(mockArticleRepository.Object);
    var result = await articleRepository.GetArticleAsync(1);

    Assert.NotNull(result);
    Assert.Equal(FakeDb.Articles.First(), result);
}

First, we instantiate the FakeDbArticleMock class and indicate which setup we want to use for this test. Then, it is necessary to instantiate the repository we want to test and inject the mock instance into it.

Finally, we call the method we are testing and assert the results.

You can check the other test methods in our source code.

Conclusion 

In this article, we’ve learned how to mock asynchronous methods using the Moq framework. We’ve also seen that Moq Framework introduced the ReturnsAsync method in version 4.2.28+, and learned how to test asynchronous methods with older versions.