在异步方法中测试异常

use*_*895 54 c# nunit async-await fluent-assertions

我对这段代码感到有些困惑(这是一个例子):

public async Task Fail()
{
    await Task.Run(() => { throw new Exception(); });
}

[Test]
public async Task TestFail()
{
    Action a = async () => { await Fail(); };
    a.ShouldThrow<Exception>();
}
Run Code Online (Sandbox Code Playgroud)

代码没有捕获异常,并且失败了

期望抛出System.Exception,但没有抛出异常.

我确定我错过了一些东西,但是文档似乎暗示这是要走的路.一些帮助将不胜感激.

Ser*_*kiy 87

您应该使用Func<Task>而不是Action:

[Test]
public void TestFail()
{
    Func<Task> f = async () => { await Fail(); };
    f.ShouldThrow<Exception>();            
}
Run Code Online (Sandbox Code Playgroud)

这将调用以下用于验证异步方法的扩展

public static ExceptionAssertions<TException> ShouldThrow<TException>(
    this Func<Task> asyncAction, string because = "", params object[] becauseArgs)
        where TException : Exception        
Run Code Online (Sandbox Code Playgroud)

在内部,此方法将运行返回的任务Func并等待它.就像是

try
{
    Task.Run(asyncAction).Wait();
}
catch (Exception exception)
{
    // get actual exception if it wrapped in AggregateException
}
Run Code Online (Sandbox Code Playgroud)

请注意,测试本身是同步的.

  • 仅供参考 - 在fluentassertions的最新版本(v5)中,语法为:f.Should().抛出<Exception> (7认同)
  • isync等待真的有必要吗?好像只用`Func <Task> f =()=> Fail();` (4认同)
  • 如果您有兴趣在测试之前等待调用完成执行。 (2认同)

gat*_*sby 15

使用Fluent Assertions v5 +,代码将类似于:

ISubject sut = BuildSut();
//Act and Assert
Func<Task> sutMethod = async () => { await sut.SutMethod("whatEverArgument"); };
await sutMethod.Should().ThrowAsync<Exception>();
Run Code Online (Sandbox Code Playgroud)

这应该工作。

  • 难道没有等待吗?等待sutMethod.Should()。ThrowAsync &lt;Exception&gt;();` (3认同)
  • 我认为在第三行中, async-await 关键字对是不必要的,没有它也适用于我。 (3认同)