首页 文章

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

提问于
浏览
18

根据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 传递 .

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

1 回答

  • 8

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

    这就像说:

    public string Name { get; set; }
    

    相当于:

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

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

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

    不可否认,编写单元测试返回 Task 但不使用异步方法至少是不寻常的 - 但这绝非不可能 .

相关问题