如何验证是否为引发异常的 Class 调用了方法

How to Verify if a Method Is Invoked for a Class That Throws an Exception

我有以下测试方法。我想在这个测试中实现的是验证Error方法在收到异常时被方法SendSMSAsync()调用。

[TestMethod]
public async Task SendSMSAsync_PostAsyncRequestResultedInAnException_LogExceptionAsAnError
{
    _client.Setup(clnt => clnt.PostAsync("uri", It.IsAny<HttpContent>()))
        .ThrowsAsync(new Exception("Exception!"));
    var service = new SMSService();
    
    _ = service.SendSMSAsync("mobile_number");

    _logger.Verify(lgr => lgr.Error(exception => exception.Message.Contains("Exception!")))
}

这是服务的实现。

public async Task<bool> SendSMSAsync(string mobileNumber)
{
    try
    {
        ...

        // Set up PostAsync to throw an exception.
        using (var response = _client.PostAsync("uri", content))
        {
            ...
        }
    }

    catch(Exception exception)
    {
        _logger.Error(exception);
        throw new Exception("An error has occurred while sending an SMS.");
    }
}

如果我运行这个,我的测试失败说明Test method threw an exception.。有没有办法让我验证是否在 catch 语句中调用了方法?

您可以在测试中捕获异常:

try
{
    _ = service.SendSMSAsync("mobile_number");
}
catch
{
    _logger.Verify(lgr => lgr.Error(exception => exception.Message.Contains("Exception!")));
}

为了防止误报,您还可以从 catch return 并在 catch 之后故意使测试失败。类似于:

try
{
    _ = service.SendSMSAsync("mobile_number");
}
catch
{
    _logger.Verify(lgr => lgr.Error(exception => exception.Message.Contains("Exception!")));
    return;
}
throw new Exception("Test failed!");

这里的想法是,如果方法一开始没有抛出异常,测试就不会“通过”。

请注意,测试框架内可能有一些工具可以更优雅地使测试失败,我不记得了。但是思路大体相同


旁注:该方法调用中不应该有一个 await 吗?