针对特定异常的单元测试异步方法

Per*_*ine 14 c# unit-testing async-await windows-8

有没有人有一个如何在Windows 8 Metro应用程序中单元测试异步方法的示例,以确保它抛出所需的异常?

给定一个具有异步方法的类

public static class AsyncMathsStatic
{
    private const int DELAY = 500;

    public static async Task<int> Divide(int A, int B)
    {
        await Task.Delay(DELAY);
        if (B == 0)
            throw new DivideByZeroException();
        else
            return A / B;
    }
}
Run Code Online (Sandbox Code Playgroud)

我想使用新的Async.ExpectsException构造编写测试方法.我试过了 :-

[TestMethod]
public void DivideTest1()
{
    Assert.ThrowsException<DivideByZeroException>(async () => { int Result = await AsyncMathsStatic.Divide(4, 0); });
}
Run Code Online (Sandbox Code Playgroud)

但是当然测试不会等待异步方法完成,因此导致测试失败,但没有抛出异常.

Ste*_*ary 16

您可以使用async Task常规单元测试ExpectedExceptionAttribute:

[TestMethod]
[ExpectedException(typeof(DivideByZeroException))]
public async Task DivideTest1()
{
  int Result = await AsyncMathsStatic.Divide(4, 0);
}
Run Code Online (Sandbox Code Playgroud)

从评论更新: ExpectedExceptionAttribute关于Win8的单元测试项目已被替换Assert.ThrowsException,这是很好的无证AFAICT.这是一个很好的改变设计明智的,但我不知道为什么它支持Win8的.

那么,假设没有async兼容的Assert.ThrowsException(我不知道如果有一个或不是由于缺少文件),你可以自己建立一个:

public static class AssertEx
{
  public async Task ThrowsExceptionAsync<TException>(Func<Task> code)
  {
    try
    {
      await code();
    }
    catch (Exception ex)
    {
      if (ex.GetType() == typeof(TException))
        return;
      throw new AssertFailedException("Incorrect type; expected ... got ...", ex);
    }

    throw new AssertFailedException("Did not see expected exception ...");
  }
}
Run Code Online (Sandbox Code Playgroud)

然后使用它:

[TestMethod]
public async Task DivideTest1()
{
  await AssertEx.ThrowsException<DivideByZeroException>(async () => { 
      int Result = await AsyncMathsStatic.Divide(4, 0);
  });
}
Run Code Online (Sandbox Code Playgroud)

请注意,我的示例只是对异常类型进行精确检查; 您可能也希望允许后代类型.

更新2012-11-29:打开UserVoice建议将其添加到Visual Studio.


Min*_*ind 8

[TestMethod]
public void DivideTest1()
{
    Func<Task> action = async () => { int Result = await AsyncMathsStatic.Divide(4, 0); });
    action.ShouldThrow<DivideByZeroException>();
}
Run Code Online (Sandbox Code Playgroud)

使用.ShouldThrow()FluentAssertions nuget 包对我有用


Lia*_*iam 5

通过添加方法ThrowsExceptionAsync现在可以在本地覆盖此内容,而无需 MSTest 中的第三方或扩展方法:

await Assert.ThrowsExceptionAsync<Exception>(() => { Fail(); });
Run Code Online (Sandbox Code Playgroud)