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

14

我正在使用xUnit和Moq编写测试用例。

我在测试类中使用以下代码来测试另一个类方法的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);
}
在下面的代码中,我想返回 Exception 而不是 BadRequest。
mockClient.Setup(repo => repo.SendAsync(It.IsAny<HttpRequestMessage>(), It.IsAny<string>()))
    .Returns(() => Task.FromResult(new HttpResponseMessage(HttpStatusCode.BadRequest)));

如何实现。


2
抛出异常,而不是返回... - Johnny
2个回答

30

考虑到被测试代码的异步性质,最好的方式是使测试代码也异步化。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);
}

请注意在设置中使用了Moq的ReturnsAsyncThrowsAsync,以及xUnit的Assert.ThrowsAsync

现在,您可以避免进行可能导致死锁的阻塞调用,如.Result


感谢您的建议。当我遇到问题时,StackOverflow从来不让我失望。解释得非常好。问题已解决。 - chandra sekhar

5
正如评论中@Johnny提到的那样,你可以将代码中的Returns替换为Throws,例如:

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

此外,您还可以像以下方式抛出异常:

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

你可以在这里找到有关抛出异常和moq的更多信息。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接