xUnit异步测试无法正常工作

问题描述 投票:16回答:1

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

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

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

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

这是两个小方法。

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

正如您只能看到差异,第一个方法定义为“async”,这里是对这些方法的两个测试。

  [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);
    }

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

XunitTestMethod_Async测试通过,但XunitTestMethod_Normal失败。抛出异常并非如此,您可以根据需要更改方法内容AsyncTestMethod始终传递。

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

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

希望你能赐教。

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

unit-testing async-await xunit
1个回答
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调用并捕获任何异常。

© www.soinside.com 2019 - 2024. All rights reserved.