当async / await关键字未被使用时,为什么异步单元测试会失败?

时间:2015-01-20 19:10:02

标签: c# unit-testing nunit async-await mstest

根据this discussion,以下两种方法之间应该没有区别:

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

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

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

然而,这显然并不总是在单元测试中起作用。

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通过。

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

1 个答案:

答案 0 :(得分:8)

听起来那些测试运行者可能正在使用反射来检查返回Task的方法是否真的异步方法。这并不意味着该方法的运行方式不同如果它们已经运行 - 但它们只是没有被运行。

就像说:

public string Name { get; set; }

相当于:

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

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

在当前的NUnit代码中(在撰写本文时),检测位于AsyncInvocationRegion.cs

不可否认,至少异常写一个单元测试返回Task但没有使用异步方法 - 但这绝非不可能。