C# 当使用匿名异步方法调用方法时,xUnit测试挂起/死锁
我有一个xUnit(2.1.0)测试,它总是挂起/死锁。此处,为了清晰和保密,更改了类/方法名称的代码:C# 当使用匿名异步方法调用方法时,xUnit测试挂起/死锁,c#,xamarin,async-await,xunit,xunit.net,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 = te
[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,测试应该通过并完成,但它只是挂起,我从来没有在运行程序上看到测试成功
以下是Dostuff TotheDocument的外观:
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)
});
}
public void CheckInTheDocFirst(Action pConfirmAction)
{
pConfirmAction(); //since this is a method in a mock class only used for testing we just call the action
}
最后这里是CheckInDocFirst的外观:
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)
});
}
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 Wait范例中是否有什么东西导致此测试挂起 当你有一个异步函数时,你应该一直都是异步的。否则,您会遇到同步上下文被阻止的问题,这将导致锁定 pContainer.checkinDocFirst应该是异步的并返回一个任务(因为它使用一个异步函数返回一个任务对象) DoStuffToDocument应该是返回任务的异步函数,因为它调用异步函数 最后,测试本身也应该是一个返回任务的异步方法
如果您一直运行async,我想您会发现一切正常。事实证明,这是由xUnit中的async void测试方法支持引起的问题: 虽然您确实应该一直使用异步,但有时由于互操作性问题,这是不可行的。你不能总是更改你正在处理的每件事的签名 但是,关于断言,需要注意的一点是,即使异步void方法(在本例中是lambda)中抛出异常,它也将始终被证明是正确的。这是因为: 异步void方法具有不同的错误处理语义。当从异步任务或异步任务方法抛出异常时,将捕获该异常并将其放置在任务对象上。对于异步void方法,没有任务对象,因此从异步void方法抛出的任何异常都将直接在异步void方法启动时处于活动状态的SynchronizationContext上引发。图2说明了异步void方法抛出的异常不能自然捕获
将
async
lambda传递给Action
参数将创建async void
方法,该方法众所周知很难测试,但不应导致死锁。你在什么地方堵车吗?(请给出一个最小但完整的示例)。@StephenCleary我不认为有任何东西会阻塞。事实上,我在测试中得到了断言,这让我相信没有任何东西是阻塞的。我遗漏的唯一代码(被测试击中的代码)是对匿名异步函数中Path类的几个调用。下面有一个更复杂的代码,但它从来没有被击中,因为我很早就返回了,我错过了它确实到达了断言;那就不堵了。你的异步lambda完成了吗?