【问题标题】:xUnit Async Test Not Working ProperlyxUnit 异步测试无法正常工作
【发布时间】:2014-07-12 13:02:54
【问题描述】:

我们从一开始就在我们的项目中使用 xUnit 框架作为测试框架。目前项目中有 2200 多个单元测试,一切正常。

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

经过更多研究后,我意识到这些测试必须失败但似乎通过了,因为所有这些测试都标有“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");
}

正如您所看到的唯一区别,第一个方法定义为“异步” 以下是对这些方法的两个测试。

  [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

【问题讨论】:

  • 尝试将async void 签名更改为async Task 以获取XunitTestMethod_Async。我记得以前看到过类似的问题被问及回答,但找不到。
  • @Noseratio 太棒了。我想不出答案就这么简单。如果您发表评论答案,我愿意接受。非常感谢。

标签: unit-testing async-await xunit


【解决方案1】:

问题是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 指出的那样,async void 测试现在都失败了,因为它们原本应该表现得如此。 xUnit 团队已经实现了AsyncTestSyncContext,这是他们特殊的同步上下文,他们使用一个实例来单独跟踪每个async void 调用并捕获任何异常。

【讨论】:

  • async void 非常有趣和奇怪的怪癖,但这绝对是有道理的。我偶然发现了这个问题,但我很高兴读到它。
  • 今天仍然如此吗?
  • @maracuja-juice,我相信是这样,但我不使用 xUnit。你能试着报告一下吗?
  • @maracuja-juice,哪些失败了,async void?看来他们现在确实有自己的AsyncTestSyncContext,每个async void 方法调用都必须安装一个实例。
  • @noseratio 两个测试都失败了。这是预期的结果。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多