为什么在不使用async / await关键字时异步unit testing失败?

根据这个讨论 ,以下两种方法应该没有区别:

public async Task Foo() { await DoSomethingAsync(); } public Task Foo() { return DoSomethingAsync(); } 

实际上,似乎对于非常简单的方法, 没有 async / await关键字的调用将是首选,因为它们会消除一些开销。

然而,这显然并不总是在unit testing中起作用。

MSTest的

 [TestClass] public class AsyncTest { [TestMethod] public async Task Test1() { await Task.Delay(0); } [TestMethod] public Task Test2() { return Task.Delay(0); } } 

NUnit的

 [TestFixture] public class AsyncTest { [Test] public async Task Test1() { await Task.Delay(0); } [Test] public Task Test2() { return Task.Delay(0); } } 

的xUnit

 public class AsyncTest { [Fact] public async Task Test1() { await Task.Delay(0); } [Fact] public Task Test2() { return Task.Delay(0); } } 
  • 在所有情况下, Test1通过了。
  • 在MSTest中, Test2出现在测试运行器中,但它没有运行。
  • 在NUnit中,将忽略Test2 ,并显示以下消息:

    测试方法具有非void返回类型,但不期望结果

  • 在XUnit中, Test2通过。

由于任务仍在等待所有情况,因此影响NUnit和MSTest测试运行器的async关键字是什么? 或许有些反思问题?

听起来那些测试运行器可能正在使用reflection来检查返回Task的方法是否真的异步方法。 这并不意味着如果它们被运行,该方法会表现得不同 – 但它们只是没有被运行。

这就像说:

 public string Name { get; set; } 

相当于:

 private string name; public Name { get { return name; } set { name = value; } } 

它们在行为方面在逻辑上是相同的,但如果你用reflection努力,你可以分辨出来。 在这种特殊情况下,还有其他更微妙的差异,但同样的一般原则适用。

它看起来像在当前的NUnit代码中(在撰写本文时),检测是在AsyncInvocationRegion.cs

不可否认,编写unit testing返回Task但不使用异步方法至少是不寻常的 – 但这绝非不可能。