Paul Cavacas
Paul Cavacas

Reputation: 4454

Setting up a C# Test with Moq against Async methods

I'm trying to create a set of test methods using Moq to cover the external dependencies. These dependencies are async in nature and I have come across a set of them that when awaited they never return, so I'm not sure what I'm missing.

The test itself is very simple.

[TestMethod]
public async Task UpdateItemAsync()
{
    var repository = GetRepository();
    var result = await repository.UpdateItemAsync("", new object());
    Assert.IsNotNull(result);
}

The GetRepository method above is what sets up the various mock objects including called Setup on them.

private static DocumentDbRepository<object> GetRepository()
{
    var client = new Mock<IDocumentClient>();
    var configuration = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build();

    client.Setup(m => m.ReplaceDocumentAsync(It.IsAny<Uri>(), It.IsAny<object>(), It.IsAny<RequestOptions>()))
        .Returns(() =>
        {
            return new Task<ResourceResponse<Document>>(() => new ResourceResponse<Document>());
        });

    var repository = new DocumentDbRepository<object>(configuration, client.Object);
    return repository;
}

The code that is under test is listed below and when the line with the await is executed it never returns.

public async Task<T> UpdateItemAsync(string id, T item)
{
    var result = await Client.ReplaceDocumentAsync(UriFactory.CreateDocumentUri(DatabaseId, CollectionId, id), item);
    return result.Resource as T;
}

I'm sure that the error is in the Setup method on the Moq object in the GetRepository method, but I'm not sure what the problem is.

Upvotes: 2

Views: 6760

Answers (1)

Nkosi
Nkosi

Reputation: 247631

You need to fix the set up on the async calls

Moq has a ReturnsAsync that would allow the mocked async method calls to flow to completion.

client
    .Setup(_ => _.ReplaceDocumentAsync(It.IsAny<Uri>(), It.IsAny<object>(), It.IsAny<RequestOptions>()))
    .ReturnsAsync(new ResourceResponse<Document>());

You typically want to avoid newing up Tasks manually

Upvotes: 8

Related Questions