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

Mat*_*int 19 c# nunit unit-testing mstest async-await

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

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

public Task Foo()
{
    return DoSomethingAsync();
}
Run Code Online (Sandbox Code Playgroud)

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

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

MSTest的

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

    [TestMethod]
    public Task Test2()
    {
        return Task.Delay(0);
    }
}
Run Code Online (Sandbox Code Playgroud)

NUnit的

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

    [Test]
    public Task Test2()
    {
        return Task.Delay(0);
    }
}
Run Code Online (Sandbox Code Playgroud)

的xUnit

public class AsyncTest
{
    [Fact]
    public async Task Test1()
    {
        await Task.Delay(0);
    }

    [Fact]
    public Task Test2()
    {
        return Task.Delay(0);
    }
}
Run Code Online (Sandbox Code Playgroud)
  • 在所有情况下,Test1通过.
  • 在MSTest中,Test2显示在测试运行器中,但它不会运行.
  • 在NUnit中,将Test2被忽略,并显示以下消息:

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

  • 在XUnit中,Test2传递.

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

Jon*_*eet 8

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

这就像说:

public string Name { get; set; }
Run Code Online (Sandbox Code Playgroud)

相当于:

private string name;
public Name { get { return name; } set { name = value; } }
Run Code Online (Sandbox Code Playgroud)

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

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

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

  • @MattJohnson:当然你可以自己添加这个属性,我怀疑 - 只是为了欺骗它.可能值得尝试看看MSTest做了什么...... (2认同)
  • 是的.添加了`[AsyncStateMachine(typeof(Task))]`,现在在MSTest和NUnit下传递.虽然我认为我只会坚持使用async/await关键字.:) (2认同)