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

Why do async unit tests fail when the async/await keywords aren't used?

根据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);
    }
}

N个单位

[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 出现在测试 运行ner 中,但没有出现 运行。
  • 在 NUnit 中,Test2 被忽略,消息为:

    Test method has non-void return type, but no result is expected

  • 在 XUnit 中,Test2 通过。

由于任务在所有情况下仍然是可等待的,那么影响 NUnit 和 MSTest 测试 运行 人员的 async 关键字是什么?也许是一些反射问题?

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

等于说:

public string Name { get; set; }

相当于:

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

它们在行为上在逻辑上是相同的,但如果你足够努力地反思,你就能分辨出不同之处。在这种特殊情况下,还有其他更细微的差异,但适用相同的一般原则。

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

诚然,编写单元测试返回 Task 但不使用异步方法至少 不寻常 - 但远非不可能。