Ste*_*ter 4 c# mstest async-await
我有Visual Studio 2012和需要同步上下文的异步测试.
但是MSTest的默认同步上下文为null.
我想测试在具有同步上下文的WPF或WinForms-UI线程上运行.
将SynchronizationContext添加到测试线程的最佳方法是什么?
[TestMethod]
public async Task MyTest()
{
Assert.IsNotNull( SynchronizationContext.Current );
await MyTestAsync();
DoSomethingOnTheSameThread();
}
Run Code Online (Sandbox Code Playgroud)
您可以创建自定义的SynchronizationContext派生类,并使用SynchronizationContext.SetSynchronizationContext将其注册为当前上下文.阅读Stephen Toub关于" Await,SynchronizationContext和Console Apps "和" Await,SynchronizationContext和Console Apps:Part 2 " 的帖子.
您的自定义SynchronizationContext只需覆盖接收异步执行回调的Post方法.你如何执行它们取决于你.
第一篇文章提供了一个同步上下文,它将所有发布的操作存储在一个队列中,一个阻塞循环从队列中获取操作并在单个线程中执行它们.
使用Panagiotis Kanavos和Stephen Cleary的信息,我可以像这样编写我的测试方法:
[TestMethod]
public void MyTest()
{
Helper.RunInWpfSyncContext( async () =>
{
Assert.IsNotNull( SynchronizationContext.Current );
await MyTestAsync();
DoSomethingOnTheSameThread();
});
}
Run Code Online (Sandbox Code Playgroud)
内部代码现在在WPF同步上下文中运行,并处理用于MSTest的所有异常.Helper方法来自Stephen Toub:
using System.Windows.Threading; // WPF Dispatcher from assembly 'WindowsBase'
public static void RunInWpfSyncContext( Func<Task> function )
{
if (function == null) throw new ArgumentNullException("function");
var prevCtx = SynchronizationContext.Current;
try
{
var syncCtx = new DispatcherSynchronizationContext();
SynchronizationContext.SetSynchronizationContext(syncCtx);
var task = function();
if (task == null) throw new InvalidOperationException();
var frame = new DispatcherFrame();
var t2 = task.ContinueWith(x=>{frame.Continue = false;}, TaskScheduler.Default);
Dispatcher.PushFrame(frame); // execute all tasks until frame.Continue == false
task.GetAwaiter().GetResult(); // rethrow exception when task has failed
}
finally
{
SynchronizationContext.SetSynchronizationContext(prevCtx);
}
}
Run Code Online (Sandbox Code Playgroud)
您可以SynchronizationContext在我的AsyncEx库中使用单线程调用AsyncContext:
[TestMethod]
public void MyTest()
{
AsyncContext.Run(async () =>
{
Assert.IsNotNull( SynchronizationContext.Current );
await MyTestAsync();
DoSomethingOnTheSameThread();
});
}
Run Code Online (Sandbox Code Playgroud)
但是,这并没有完全伪造特定的UI环境,例如,Dispatcher.CurrentDispatcher仍将是null.如果您需要这种级别的伪造,则应使用SynchronizationContext原始Async CTP中的实现.它附带了三个SynchronizationContext可用于测试的实现:一个通用的(类似于我的AsyncContext),一个用于WinForms,一个用于WPF.
| 归档时间: |
|
| 查看次数: |
4767 次 |
| 最近记录: |