简体   繁体   English

如何使用 Moq 为异步函数抛出异常

[英]How can I throw Exception for async function using Moq

I am writing test cases using xUnit and Moq.我正在使用 xUnit 和 Moq 编写测试用例。

I am using below code in Test class for testing catch() of another class method我在测试类中使用以下代码来测试另一个类方法的catch()

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 .在下面的代码中,我想返回 Exception 而不是BadRequest

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

How to achieve that.如何实现这一目标。

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 Moq 具有异步能力

[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请注意在设置中使用 Moq 的ReturnsAsyncThrowsAsync ,以及 xUnit 的Assert.ThrowsAsync

This now allows you to avoid making blocking calls like .Result which could potentially lead to deadlocks.这现在允许您避免进行像.Result这样可能导致死锁的阻塞调用。

As @Johnny mentioned in the comments, you can replace the Returns in your code with Throws like:正如@Johnny 在评论中提到的,您可以用Throws替换代码中的Returns ,例如:

mockClient.Setup(repo => repo.SendAsync(It.IsAny<HttpRequestMessage>(), It.IsAny<string>()))
  .Throws(new Exception("exception message"));

In addition, you could also throw an exception like:此外,您还可以抛出如下异常:

mockClient.Setup(repo => repo.SendAsync(It.IsAny<HttpRequestMessage>(), It.IsAny<string>()))
  .Throws<InvalidOperationException>();

You can find more information about throwing exceptions and moq here .您可以在此处找到有关抛出异常和最小起订量的更多信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM