Unit testing xUnit异步测试工作不正常
我们从一开始就在项目中使用xUnit框架作为测试框架。目前项目中有2200多个单元测试,一切都很好 但昨天我决定在CI构建和夜间构建中运行单元测试。与team build controller一起运行xunit测试1-2个小时,我成功地运行了测试。但有一个问题,有22个关于如下测试的警告, -Xunit.Sdk.EqualException:Assert.Equal()失败 或 -System.ArgumentNullException:值不能为null 经过进一步研究,我意识到这些测试必须失败,但似乎通过了,因为所有这些测试都标有“async”关键字 实际上不应该有任何错误,因为xUnit支持关于这些帖子的异步测试 然而,现实对我来说差别不大。是的,xUnit运行没有任何问题,但测试不正确 这里有两个小方法Unit testing xUnit异步测试工作不正常,unit-testing,async-await,xunit,Unit Testing,Async Await,Xunit,我们从一开始就在项目中使用xUnit框架作为测试框架。目前项目中有2200多个单元测试,一切都很好 但昨天我决定在CI构建和夜间构建中运行单元测试。与team build controller一起运行xunit测试1-2个小时,我成功地运行了测试。但有一个问题,有22个关于如下测试的警告, -Xunit.Sdk.EqualException:Assert.Equal()失败 或 -System.ArgumentNullException:值不能为null 经过进一步研究,我意识到这些测试必须失败
public async Task<string> AsyncTestMethod() {
throw new Exception("Test");
}
public string NormalTestMethod() {
throw new Exception("Test");
}
[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\u异步测试通过,但XunitTestMethod\u正常失败。
抛出异常不是这种情况,您可以根据需要更改方法内容AsyncTestMethod始终通过
以下是示例解决方案:
我可能会误解或认为错误,但现在这种行为给我带来了很多痛苦
希望你能启发我
PS:我在XUnitGithub页面上创建了一个问题,但我不能确定这是由我还是xUnit引起的。所以我也决定在这里提问。
问题:问题在于
async void
方法不返回xUnit可能检查异常的Task
对象。xUnit甚至无法跟踪特定的异步void
方法的完成情况,而不是异步任务
方法
此外,async void
方法不会在同一堆栈帧上抛出异常,即使是从方法的同步部分抛出的异常也是如此。相反,异常通过SynchronizationContext.Post
(如果SynchronizationContext.current!=null
)或通过ThreadPool.QueueUserWorkItem
传播到当前同步上下文。此行为不同于异步任务方法。可以跟踪挂起的async void
方法的总数(通过SynchronizationContext.OperationStarted
/OperationCompleted
),但不能跟踪单个方法
因此,将XunitTestMethod\u Async
方法的签名从Async void
更改为Async Task
应该可以解决问题
更新了,现在是2019年,@maracuja juice指出,两个异步void
测试现在都失败了,因为它们本来应该是这样的。xUnit团队已经实现了他们独特的同步上下文,一个他们用来单独跟踪每个async void
调用并捕获任何异常的实例。尝试将async void
签名更改为async任务
。我记得以前看到过一个类似的问题被问到和回答过,但我没有发现。我想答案不会这么简单。如果你发表你的评论,我愿意接受。非常感谢。关于async void
非常有趣和奇怪,但它确实有意义。我偶然发现了这个问题,但我很高兴读到它。这在今天仍然成立吗?@maracuja juice,我相信是的,但我不使用xUnit。你能试着报告吗?@maracuja juice,哪些失败,async void
?现在他们似乎有了自己的实例,每个async void
方法调用都必须安装一个实例,但两个测试都失败了。这正是人们所期望的。