How to return a Task<string> using Moq?

Viewed 3751

I am using XUnit and Moq to test code from my logic layer. My logic layer also communicates with the data layer, so I want to mock the interface to keep my test simple.

I am wondering how I should return a Task<string> when I call the async Task method. My GetOrder method calls GetOrderById but the data layer method returns null.

Edit: I changed my unit test based on all the feedback. It works fine now.
My test:

public async void GetOrder()
{
    //Arrange 
    string expected = "test";
    
    var mock = new Mock<IRepository>();
    mock.Setup(arg => arg.GetOrderNameById(It.IsAny<int>())
        .Returns(Task.FromResult(expected));
    var survey = new SurveyResult(mock.Object);

    //Act 
    string result = await survey.GetOrderNameById(It.IsAny<int>()));

    //Assert
    Assert.Equal(expected, result);
}
2 Answers

Use Task.FromResult(expected)

mock.Setup(arg => arg.GetScoreByTotalWeighting(value)).Returns(Task.FromResult(expected))

also I'd recomend to avoid value as parameter, when you dont care about that paramter when returning result. You can use It.IsAny<int>(), like that:

mock.Setup(arg => arg.GetScoreByTotalWeighting(It.IsAny<int>())).Returns(Task.FromResult(expected))

Problem that you setting up mock.Setup(arg => arg.GetScoreByTotalWeighting(value)) with value == 0 and then call survey.GetResult(score) with 50. Use It.IsAny<int>() at both places to avoid that problem, or pass same value:

mock.Setup(arg => arg.GetScoreByTotalWeighting(score))

Solution:

public async Task GetResult()
{
    //Arrange 
    string expected = "test";

    var mock = new Mock<IRetreiveQuestionRepository>();
    mock.Setup(arg => arg.GetScoreByTotalWeighting(It.IsAny<int>()))
        .ReturnsAsync(expected);
    var survey = new SurveyResult(mock.Object);

    //Act 
    string result = await survey.GetResult(It.IsAny<int>());

    //Assert
    Assert.Equal(expected, result);
}

You should be able to use the .ReturnsAsync method you're currently using, It's hard to tell why your subject is returning null without knowing the implementation. But I would double check the stubbing to see if you're specifying the value that is indeed passed to the real implementation or if you're missing any other stubbing for another method. Hope that helps :)

Related