为什么 ConfigureAwait(true) 在单元测试中不起作用?
Why ConfigureAwait(true) does not work on unit tests?
默认情况下,单元测试不会捕获 运行 所在的 SynchronizationContext
,因此如果您这样写:
[TestMethod]
public async Task AwaitThreadSwitch()
{
WriteThread();
await Do();
WriteThread();
}
private Task Do()
{
return Task.Run(() =>
{
WriteThread();
Thread.Sleep(50);
});
}
private void WriteThread()
{
Debug.WriteLine($"CURRENT THREAD: {Thread.CurrentThread.ManagedThreadId}");
}
您获得以下输出:
CURRENT THREAD: 8
CURRENT THREAD: 6
CURRENT THREAD: 6
没关系:一旦 await
被调用并且 returns,流不会 return 到原始线程。
现在,如果我这样写测试方法:
[TestMethod]
public async Task AwaitThreadSwitch()
{
WriteThread();
await Do().ConfigureAwait(true); // <-- note this change
WriteThread();
}
我预计:
CURRENT THREAD: 8
CURRENT THREAD: 6
CURRENT THREAD: 8 // <-- back to the main Thread
相反,我得到了与第一次测试相同的结果。
为什么不将执行编组回测试方法的主线程?
您似乎误解了为什么在您的第一个示例中测试没有编组回主线程。这不是因为某处隐式设置了 ConfigureAwait(false)
。而是因为没有同步上下文.
您的两个测试实际上是相同的。调用 ConfigureAwait(true)
与根本不调用它没有什么不同。只是没有上下文可以返回,默认的同步上下文行为只是在同一个线程中继续。
所以,这就是您在两个测试中看到的。因为这两个测试确实做同样的事情。
默认情况下,单元测试不会捕获 运行 所在的 SynchronizationContext
,因此如果您这样写:
[TestMethod]
public async Task AwaitThreadSwitch()
{
WriteThread();
await Do();
WriteThread();
}
private Task Do()
{
return Task.Run(() =>
{
WriteThread();
Thread.Sleep(50);
});
}
private void WriteThread()
{
Debug.WriteLine($"CURRENT THREAD: {Thread.CurrentThread.ManagedThreadId}");
}
您获得以下输出:
CURRENT THREAD: 8
CURRENT THREAD: 6
CURRENT THREAD: 6
没关系:一旦 await
被调用并且 returns,流不会 return 到原始线程。
现在,如果我这样写测试方法:
[TestMethod]
public async Task AwaitThreadSwitch()
{
WriteThread();
await Do().ConfigureAwait(true); // <-- note this change
WriteThread();
}
我预计:
CURRENT THREAD: 8
CURRENT THREAD: 6
CURRENT THREAD: 8 // <-- back to the main Thread
相反,我得到了与第一次测试相同的结果。
为什么不将执行编组回测试方法的主线程?
您似乎误解了为什么在您的第一个示例中测试没有编组回主线程。这不是因为某处隐式设置了 ConfigureAwait(false)
。而是因为没有同步上下文.
您的两个测试实际上是相同的。调用 ConfigureAwait(true)
与根本不调用它没有什么不同。只是没有上下文可以返回,默认的同步上下文行为只是在同一个线程中继续。
所以,这就是您在两个测试中看到的。因为这两个测试确实做同样的事情。