为啥不能识别“异步无效”单元测试?

Posted

技术标签:

【中文标题】为啥不能识别“异步无效”单元测试?【英文标题】:Why can't "async void" unit tests be recognized?为什么不能识别“异步无效”单元测试? 【发布时间】:2013-10-19 11:23:16 【问题描述】:

async void 单元测试无法在 Visual Studio 2012 中运行:

[TestClass]
public class MyTestClass

    [TestMethod]
    public async void InvisibleMyTestMethod()
    
        await Task.Delay(1000);
        Assert.IsTrue(true);
    

如果我想进行异步单元测试,测试方法必须返回一个任务:

[TestMethod]
public async Task VisibleMyTestMethod()

    await Task.Delay(1000);
    Assert.IsTrue(true);

为什么会这样?并不是说我绝对需要async void 测试方法,我只是好奇。当您构建 async void 测试方法时,即使它无法运行,Visual Studio 2012 也不会发出警告或错误...

【问题讨论】:

【参考方案1】:

我在 VS2015 中发现任何用 async 修饰的测试方法都不会显示在测试资源管理器中。我最终删除了 async 关键字并将测试中的 await 调用替换为 task.Wait() 并对 task.Result 进行了断言。

似乎工作正常。还没有尝试过异常测试。

var task = TheMethodIWantToTestAsync(someValue);
task.Wait();
var response = task.Result;

Assert.IsNotNull(response);
Assert.IsTrue(response.somevalue);

【讨论】:

不要认为它需要调用task.Wait(),因为调用task.Result如果任务没有完成会自动调用task.Wait()。【参考方案2】:

这只是因为 MSTest 不支持 async void 单元测试。 可能通过引入它们可以执行的上下文来做到这一点。

MSTest 不支持这一点,可能是因为 Microsoft 认为它对现有测试的改动太大(如果给定一个意外的上下文,现有测试可能会死锁)。

没有编译器警告/错误,因为它是完全有效的 C# 代码。它不起作用的唯一原因是单元测试框架(即,我相信 xUnit 确实支持async void 测试),这将严重违反 C# 编译器查看您的属性的关注点分离,确定您正在使用 MSTest,并确定您确实不想使用async void

【讨论】:

在第一个实现(Visual Studio 预览版)中,测试将被识别并“运行”。问题是该方法将在第一次等待时结束,这就是测试的结果。【参考方案3】:

async void 方法应该被视为“一劳永逸”——没有办法等待它们完成。如果 Visual Studio 开始其中一项测试,它将无法等待测试完成(将其标记为成功)或捕获任何引发的异常。

使用async Task,调用者可以等待执行完成,并捕获运行时引发的任何异常。

有关async voidasync Task 的更多讨论,请参阅this answer。

【讨论】:

这不是真的。 NUnit 确实支持async void 测试,以及如何以及为什么支持它在这个link 中有一定程度的详细说明。请参阅下面的answer。

以上是关于为啥不能识别“异步无效”单元测试?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的模拟对象不能识别对它的任何调用?

为啥我必须切换纹理单元才能让我的片段着色器识别要使用的纹理?

为啥使用集成测试而不是单元测试是一个坏主意?

为啥 PyCharm 无法运行单元测试?

iOS 单元测试包:为啥要启动该应用程序?

为啥?单元测试覆盖率中显示的类即使没有添加到测试目标中