繁体   English   中英

使用匿名Async方法调用方法时,xUnit测试挂起/死锁

[英]xUnit test hangs/deadlocks when calling method with anonymous Async method

我有一个始终挂起/死锁的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为空,并且测试应该通过并完成,但是它挂起了,我从没有在赛跑者身上看到“测试成功”。

这是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中的异步void测试方法支持引起的问题: https : //github.com/xunit/xunit/issues/866#issuecomment-223477634

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

但是,关于您的断言要注意的一件事是,即使异步void方法(在这种情况下为lambda)中引发了异常,它也将始终证明是正确的。 这是因为异步void的异常处理不同

异步void方法具有不同的错误处理语义。 从异步Task或异步Task方法抛出异常时,将捕获该异常并将其放置在Task对象上。 使用异步void方法时,没有Task对象,因此从异步void方法抛出的任何异常都将直接在启动异步void方法时处于活动状态的SynchronizationContext上引发。 图2说明了从异步void方法引发的异常不能自然地捕获。

当您具有异步功能时,您实际上应该一直处于异步状态。 否则,您将遇到同步上下文被阻止的问题,这将导致锁定。

pContainer.CheckInTheDocFirst应该是异步的,并返回一个Task(因为它采用了一个异步函数,该函数返回Task对象)。

DoStuffToDocument应该是一个返回Task的异步函数,因为它调用了异步函数。

最后,测试本身也应该是一个返回任务的异步方法。

如果您一直在堆栈上运行异步,那么我认为您会发现一切正常。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM