c# - 使用匿名异步方法调用方法时,xUnit 测试挂起/死锁

标签 c# xamarin async-await xunit xunit.net

我有一个 xUnit (2.1.0) 测试总是挂起/死锁。为了清晰和保密,这里更改了带有类/方法名称的代码:

[Fact]
public void DocumentModificationTest()
{
    Exception ex = null;
    using (TestDependency testDependency = new TestDependency())
    {
        TestDependencyDocument testDependencyDoc = testDependency.Document;
        MockTestDependency fakeDependency = new MockTestDependency();
        try
        {
            DoStuffToTheDocument(testDependencyDoc, "fileName.doc", fakeDependency);
        }
        catch (Exception e)
        {
            ex = e;
        }
    }
    Assert.Null(ex);
}

如果我设置一个断点并越过断言,我可以看到 ex 为 null 并且测试应该通过并完成,但它只是挂起并且我从未在运行器上看到 Test Successful。

这是 DoStuffToTheDocument 的样子:

public static void DoStuffToTheDocument(TestDependencyDocument document, string pFileName, MockTestDependency pContainer)
{
    pContainer.CheckInTheDocFirst(async () =>
    {
        //check some stuff
        //test returns early here

        //check other stuff(test never gets here)
        //await method (thus the async anonymous method)
    });
}

最后是 CheckInTheDocFirst 的样子:

public void CheckInTheDocFirst(Action pConfirmAction) 
{
    pConfirmAction(); //since this is a method in a mock class only used for testing we just call the action
}

有什么想法吗?我的 async-await 范式是否有什么导致此测试挂起?

最佳答案

事实证明,这是由xUnit 中的async void 测试方法支持引起的问题:https://github.com/xunit/xunit/issues/866#issuecomment-223477634

虽然您确实应该一直采用异步,但有时由于互操作性问题,这是不可行的。您不能总是更改您正在使用的所有内容的签名。

然而,关于您的断言需要注意的一件事是,即使在 async void 方法(在本例中为 lambda)中抛出异常,它也将始终证明为真。这是因为 exception handling is different for async void :

Async void methods have different error-handling semantics. When an exception is thrown out of an async Task or async Task method, that exception is captured and placed on the Task object. With async void methods, there is no Task object, so any exceptions thrown out of an async void method will be raised directly on the SynchronizationContext that was active when the async void method started. Figure 2 illustrates that exceptions thrown from async void methods can’t be caught naturally.

关于c# - 使用匿名异步方法调用方法时,xUnit 测试挂起/死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37602169/

相关文章:

c# - GridView 验证

c# - Xamarin Forms 中缺少默认构造函数错误

javascript - 在 Javascript 的 for 循环中返回 promise 的有效方法是什么

javascript - 如何做出 JSON.parse promise ? (或异步)

c# - 我的代码中出现"Specified element is already the logical child of another element. Disconnect it first"错误,有什么解决办法吗?

c# - Action 的 MVC4 查询字符串

c# - 如何在 Xamarin.Forms 中重用父 ContentView 中定义的样式

xamarin - 如何在 Xamarin 中可靠地捕获*所有* iOS 异常?

javascript - 检测 Javascript/ECMAScript 等待滥用?

c# - 在非 UWP 应用程序中使用 Windows Mixed Reality