Search code examples
c#unit-testing.net-coremoqxunit

How can I throw Exception for async function using Moq


I am writing test cases using xUnit and Moq.

I am using below code in Test class for testing catch() of another class method

private readonly  IADLS_Operations _iADLS_Operations;

[Fact]
public void CreateCSVFile_Failure()
{
    var dtData = new DataTable();
    string fileName = "";
   var   mockClient = new Mock<IHttpHandler>();

    this._iADLS_Operations = new ADLS_Operations(mockClient.Object);

    mockClient.Setup(repo => repo.PostAsync(It.IsAny<string>(), It.IsAny<HttpContent>(), It.IsAny<string>()))
        .Returns(() => Task.FromResult(new HttpResponseMessage(HttpStatusCode.BadRequest)));

    mockClient.Setup(repo => repo.SendAsync(It.IsAny<HttpRequestMessage>(), It.IsAny<string>()))
        .Returns(() => Task.FromResult(new HttpResponseMessage(HttpStatusCode.BadRequest)));  // here I want to return Exception instead of BadRequest. How to do that.

    Exception ex = Assert.Throws<Exception>(() => this._iADLS_Operations.CreateCSVFile(dtData, fileName).Result);
    Assert.Contains("Exception occurred while executing method:", ex.Message);
}

In below code, I want to return Exception instead of BadRequest.

mockClient.Setup(repo => repo.SendAsync(It.IsAny<HttpRequestMessage>(), It.IsAny<string>()))
    .Returns(() => Task.FromResult(new HttpResponseMessage(HttpStatusCode.BadRequest)));

How to achieve that.


Solution

  • Considering the asynchronous nature of the code under test, it would be better if the test code be asynchronous as well. Moq is async capable

    [Fact]
    public async Task CreateCSVFile_Failure() {
        //Arrange
        var dtData = new DataTable();
        string fileName = "";
        var mockClient = new Mock<IHttpHandler>();
    
        this._iADLS_Operations = new ADLS_Operations(mockClient.Object);
    
        mockClient
            .Setup(repo => repo.PostAsync(It.IsAny<string>(), It.IsAny<HttpContent>(), It.IsAny<string>()))
            .ReturnsAsync(new HttpResponseMessage(HttpStatusCode.BadRequest));
    
        mockClient
            .Setup(repo => repo.SendAsync(It.IsAny<HttpRequestMessage>(), It.IsAny<string>()))
            .ThrowsAsync(new Exception("Some message here"));
    
        //Act 
        Func<Task> act = () => this._iADLS_Operations.CreateCSVFile(dtData, fileName);
    
        //Assert
        Exception ex = await Assert.ThrowsAsync<Exception>(act);
        Assert.Contains("Exception occurred while executing method:", ex.Message);
    }
    

    Note the use of Moq's ReturnsAsync and ThrowsAsync in the setup, along with xUnit's Assert.ThrowsAsync

    This now allows you to avoid making blocking calls like .Result which could potentially lead to deadlocks.