xUnit异步测试无法正常工作

时间:2014-05-23 08:42:47

标签: unit-testing async-await xunit

自开始以来,我们一直在项目中使用xUnit Framework作为测试框架。目前在项目中有2200多个单元测试,一切似乎都很好。

但昨天我决定在CI版本和夜间版本中运行单元测试。与团队构建控制器战斗运行xunit测试1-2小时我成功运行测试。但有一个问题,有22个关于下面的测试的警告, - Xunit.Sdk.EqualException:Assert.Equal()失败 要么 - System.ArgumentNullException:Value不能为null。

经过一些研究后,我意识到这些测试必须失败,但似乎已经通过,因为所有这些测试都标有" async"关键字。

实际上不应该出现任何错误,因为xUnit支持关于这些帖子的异步测试 http://bradwilson.typepad.com/blog/2012/01/xunit19.html http://sravi-kiran.blogspot.com.tr/2012/11/UnitTestingAsynchronousMethodsUsingMSTestAndXUnit.html 对我来说,实力更为微不足道。是的xUnit运行没有任何问题,但没有正确测试。

这是两个小方法。

public async Task<string> AsyncTestMethod() {
    throw new Exception("Test");
}
public string NormalTestMethod() {
    throw new Exception("Test");
}

正如您只能看到差异,第一种方法被定义为&#34; async&#34; 以下是这些方法的两个测试。

  [Fact]
    public async void XunitTestMethod_Async() {
        Program p = new Program();
        string result = await p.AsyncTestMethod();
        Assert.Equal("Ok", result);
    }
        [Fact]
    public  void XunitTestMethod_Normal() {
        Program p = new Program();
        string result =  p.NormalTestMethod();
        Assert.Equal("Ok", result);
    }

两个原始方法都抛出异常,所以我认为两个测试都会失败但结果却不同。你可以看到结果: Test results

XunitTestMethod_Async测试通过,但XunitTestMethod_Normal失败。 抛出异常并非如此,您可以随意更改方法内容AsyncTestMethod始终通过。

以下是示例解决方案:https://github.com/bahadirarslan/AsyncTestWithxUnit

我可能会误解或想错,但现在这种行为给我带来了很多痛苦

希望你能引起我的注意。

PS:我在xUnit github页面上创建了一个问题,但我无法确定这是由我还是xUnit造成的。所以我决定在这里问一下。 问题:https://github.com/xunit/xunit/issues/96

1 个答案:

答案 0 :(得分:34)

问题是async void方法没有返回xUnit可能检查异常的Task对象。 xUnit甚至无法跟踪特定async void方法的完成情况,而不是async Task方法。

此外,async void方法不会在同一堆栈帧上抛出异常,即使是从方法的同步部分抛出的异常也是如此。相反,异常通过SynchronizationContext.Post(在SynchronizationContext.Current != null}中)或通过ThreadPool.QueueUserWorkItem传播到当前同步上下文。此行为与async Task方法more details不同。可以跟踪待处理async void方法的总数(通过SynchronizationContext.OperationStarted / OperationCompleted),但不能跟踪单个方法。

因此,将XunitTestMethod_Async方法的签名从async void更改为async Task可以解决问题。

已更新,它是2019年,正如@ maracuja-juice指出的那样,asynv void个测试现在都失败了,因为它们原来应该有所表现。 xUnit团队实施了AsyncTestSyncContext,这是他们特殊的同步上下文,他们安装的实例可以单独跟踪每个async void调用并捕获任何异常。