asp.netunit-testingasync-awaitmicrosoft-fakesshim

How to Unit test an AsyncTask which await another Async task?


public async Task<ResModel> GetDetails()
{
    ResModel resp = new ResModel();
    resp = await MobController.GetAllDeatails();
    return resp;
}

In the await this calls for an async task method named GetAllDeatails and returns an object ResModel.

How to properly create an unit test for this?

The unit test I've created is right below:

[TestMethod]
public async Task GetFromGetDetails()
{
    var controller = new SevicesController();
    ResModel resp = new ResModel();

    using(ShimsContext.Create())
    {
        ProjectAPI.Fakes.ShimMobController.GetAllDeatails = () => {
            resp.MessageType = "Get"
            resp.Message ="contdetail";

            return resp;
        };

        returnValueOfAsyncTask = await controller.GetDetails();

        Assert.IsNotNull(returnValueOfAsyncTask);
    }

}

This gives errors in the ShimContext creation because the return type must be async in GetAllDeatails but here it only returns the object.

Following is the main error I'm getting:

Error CS0029 Cannot implicitly convert type 'ProjectAPI.Models.ResModel' to 'System.Threading.Tasks.Task<ProjectAPI.Models.ResModel>' Un‌​itTestProjectAPI


Solution

  • The error message clearly states that it cannot convert the ResModel to a Task<ResModel> which is the return type of the method being shimmed.

    In the shim you are returning the model when the method is suppose to be returning a Task. Use Task.FromResult in order to wrap the model in a Task so that it can be return and awaited.

    In the exercising of the method under test you stated that the variable used to hold the result of the await was a Task<ResModel>. That should be changed because when you await a Task that returns a result it will just return the result not the task. So that result variable needs to be changed to from Task<ResModel> to ResModel.

    Here is the update unit test based on above changes.

    [TestMethod]
    public async Task GetFromGetDetails() {
        //Arrange
        var controller = new SevicesController();
        var expected = new ResModel();
    
        using(ShimsContext.Create()) {
    
            ProjectAPI.Fakes.ShimMobController.GetAllDeatails = () => {
                expected.MessageType = "Get"
                expected.Message ="contdetail";
    
                return Task.FromResult(expected); 
            };
    
            //Act
            var actual = await controller.GetDetails();
    
            //Assert
            Assert.IsNotNull(actual);
            Assert.AreEqual(expected, actual);
        }
    }