【问题标题】:Is it bad to have Unit Tests return async void?让单元测试返回 async void 是不是很糟糕?
【发布时间】:2017-06-29 20:42:50
【问题描述】:

我知道让方法返回 async void 是不好的做法,因为它很难测试,但是单元测试是否有任何理由需要返回 async Task 而不是 async void?

基本上可以这样:

[Test()]
public async void MyTest()
{
    //Some code to run test
    //Assert Something
}

或者我应该这样做:

[Test()]
public async Task MyTest()
{
    //Some code to run test
    //Assert Something
}

【问题讨论】:

  • 您想知道您的测试是否结束、测试何时结束以及您的测试是否成功完成?
  • 大多数单元测试运行器支持async void 方法(通过使用自定义同步上下文)。尽管如此,使用async Task 进行测试更清洁/更安全
  • @KevinGosse 在您的方法中,您仍然可以做很多事情来阻止测试框架正常工作,即使使用自定义同步上下文也是如此。 (例如,一些带有ConfigureAwait(false); 的代码就是破坏事物所需要的全部内容。)
  • @Servy 实际上,同步上下文的OperationCompleted事件只会在async void方法结束时触发,即使中间使用.ConfigureAwait(false)也是如此。我敢肯定有一些极端情况,但它比看起来更难破解。

标签: c# unit-testing asynchronous


【解决方案1】:

引用Async/Await - Best Practices in Asynchronous Programming斯蒂芬·克利里

返回无效的异步方法有一个特定的目的:使 可能的异步事件处理程序。有可能举办活动 返回一些实际类型的处理程序,但不适用于 语言;调用返回类型的事件处理程序非常 尴尬,并且事件处理程序实际上返回的概念 有些事情没有多大意义。事件处理程序自然返回 void,所以异步方法返回 void,这样你就可以有一个 异步事件处理程序。但是,异步 void 的一些语义 方法与异步任务的语义略有不同或 异步任务方法。

Async void 方法具有不同的错误处理语义。当一个 异常是从异步任务或异步任务方法中抛出的,即 异常被捕获并放置在 Task 对象上。使用异步无效 方法,没有 Task 对象,所以任何异常都会抛出 async void 方法将直接在 在异步 void 方法时处于活动状态的 SynchronizationContext 开始了。

最后几句话总结得很好。

长话短说,异步测试方法使用async Task

[Test()]
public async Task MyTest()
{
    //Some code to run test
    //Assert Something
}

您真的应该花一些时间阅读链接的文章。它的作者在该主题上有更多资源,它将帮助您理解 async/await 背后的语义

【讨论】:

  • 如果在 Assert.Thrown 期间发生的 void 测试仍然会拾取异常,对吗?只有当其他代码行抛出错误时才会出现问题?为了安全起见,我将切换到任务返回测试。
  • @NoahLarky:不,他们不会。 Task 使调用代码能够检测完成和异常。不支持 MSTest 上的 async void;它们根本不会运行。
猜你喜欢
  • 1970-01-01
  • 2011-05-09
  • 2013-04-13
  • 1970-01-01
  • 2011-10-06
  • 1970-01-01
  • 2010-10-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多