我们计划在 MVVM 视图模型中使用 async/await,但在单元测试此代码时遇到了难题。当使用 NUnit 和手写模拟来传递消息时,我们正在丢失当前的SynchronizationContext
.
最好用以下小型复制示例代码来展示:
[Test] public void TestMethod()
{
Func<Task> asyncMethod = async () =>
{
var context = SynchronizationContext.Current;
await TaskEx.Yield();
Assert.AreEqual(context, SynchronizationContext.Current);
};
// Establish the new context
var syncCtx = new SingleThreadSynchronizationContext(false);
SynchronizationContext.SetSynchronizationContext(syncCtx);
// Invoke the function and alert the context to when it completes
var t = asyncMethod();
t.ContinueWith(delegate { syncCtx.Complete(); }, TaskScheduler.Default);
// Pump continuations and propagate any exceptions
syncCtx.RunOnCurrentThread();
t.GetAwaiter().GetResult();
}
实际上,大部分代码是从 Stephen Toub 的 AsyncPump 实现中窃取的在他的博客上 http://blogs.msdn.com/b/pfxteam/archive/2012/02/02/10263555.aspx.
有趣的是,让这个测试通过所需的一切就是扔进去ExecutionContext.SuppressFlow();
在调用异步方法之前。这可能足以解决我们的问题,但我对 ExecutionContext 还不够了解,我想更深入地了解发生了什么。
为什么await语句生成的代码会吞掉当前的SynchronizationContext?
使用单线程上下文进行单元测试异步/等待代码是否还有另一种明显的方法?
PS:我们使用 .Net4 和 Microsoft.CompilerServices.AsyncTargetingPack.Net4
PPS:这也会发生在使用稳定的 Microsoft.Bcl.Async 而不是 ATP 的简单项目中
我有完全相同的问题。
我发现这是因为我的习惯SynchronizationContext
没有正确覆盖和实施CreateCopy
方法。看来异步代码在每个任务(或其他任务)之后都会创建上下文的副本。确保您的也正确实施它。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)