Darren Wainwright
Darren Wainwright

Reputation: 30747

Mock interface ReturnsAsync returning null

I am attempting to Mock an Interface that has a single Task<string> method.

The same Q here, though i can't seem to get the code to work in my favor: Setup async Task callback in Moq Framework

My interface looks like this:

public interface IHttpClient
{
    Task<string> GetStringAsync(string uri);
}

I am trying to mock this up as so:

var mockHttp = new Mock<IHttpClient>();
mockHttp.Setup(m => m.GetStringAsync("aPretendUrl")).ReturnsAsync("Some sort of string");

I am finding that the result of the GetStringAsync is null

In the controller, where this instance is injected, I am calling it as so:

string responseData = await _client.GetStringAsync(url);

Also trying

string responseData = _client.GetStringAsync(url).Result;

responseData is null in all cases.

I am sure I am missing something simple. Still new with Unit tests

Can anybody point out where I am going wrong?

Update

The full unit test looks like this:

[Test]
public void Given_EController_Called_With_unknown_pedi_Returns_NotFound()
{
    // Arrange
    AppSettings settings = new AppSettings()
    {
        DataWarehouseAPI = "http://myurl.com"
    };
    Mock<IOptionsSnapshot<AppSettings>> mockSettings = new Mock<IOptionsSnapshot<AppSettings>>();
    mockSettings.Setup(m => m.Value).Returns(settings);

    var mockHttp = new Mock<IHttpClient>();
    mockHttp.Setup(m => m.GetStringAsync("aPretendUrl")).ReturnsAsync("[]");

    EntryController controller = new EntryController(mockHttp.Object, mockSettings.Object);

     // Act
    IActionResult actionResult = controller.GetByPedimento("nothing").Result;

    // Assert
    Assert.IsAssignableFrom<NotFoundObjectResult>(actionResult);
    }

Upvotes: 6

Views: 8389

Answers (1)

rudolf_franek
rudolf_franek

Reputation: 1885

If you don't care about the 'url' in the test then you may use:

It.IsAny<string>()

result:

mockHttp.Setup(m => m.GetStringAsync(It.IsAny<string>()))
    .ReturnsAsync("Some sort of string");

If you specify 'uri' parameter in setup then you have to match it in your test to get desired return value "Some sort of string" from the method. You can specify different results for different inputs:

[TestMethod]
public async Task GetStringAsync_moqSetup()
{
    var mockHttp = new Mock<IHttpClient>();

    mockHttp.Setup(m => m.GetStringAsync(It.IsAny<string>()))
        .ReturnsAsync("Other sort of string");
    mockHttp.Setup(m => m.GetStringAsync("first"))
        .ReturnsAsync("First sort of string");

     var firstTarget = await mockHttp.Object.GetStringAsync("first");
     var differentTarget = await mockHttp.Object
         .GetStringAsync("something completely different");

    Assert.AreEqual("First sort of string", firstTarget);
    Assert.AreEqual("Other sort of string", differentTarget);
}

Review the Quickstart of the framework in order to get a better understanding of how to use it.

Upvotes: 13

Related Questions