Dar*_*rel 3 mstest winforms async-await
我有一个自定义的Windows窗体控件,其中包含MSTest单元测试.我在这个类中添加了一个异步方法,我需要覆盖它,但新测试总是超时.
经过一些实验,我把问题简化为控制创建和等待.
[TestMethod]
public async Task TestMethod1()
{
Control c = new Control();
await Task.Delay(1);
}
Run Code Online (Sandbox Code Playgroud)
我注意到测试从SynchronizationContext.Current设置开始null,然后一旦创建控件,它就会变为a WindowsFormsSynchronizationContext.如果我强制恢复同步上下文null,那么测试将通过.
[TestMethod]
public async Task TestMethod1()
{
Control c = new Control();
SynchronizationContext.SetSynchronizationContext(null);
await Task.Delay(1);
}
Run Code Online (Sandbox Code Playgroud)
有没有办法在WindowsFormsSynchronizationContext没有阻塞的情况下使用await ?
Windows窗体控件认为他们是在Windows中运行窗体应用程序,这是没有单元测试的情况.这就是你的单元测试挂起的原因.
更具体地说,WinForms控件安装一个WindowsFormsSynchronizationContext委托工作到Win32消息循环里面Application.Run.因此,您的async方法会查看上下文并将其继续排入该消息循环.但是,没有实际的消息循环,因为您的单元测试不会调用Application.Run.
最好的解决方案IMO是使用MVVM模式,您不在UI应用程序之外测试UI元素,因此您永远不会遇到这种情况(在MVVM中,您需要对逻辑 UI进行单元测试,而不是文字 UI).使用MVVM方法,您的代码将如下所示:
[TestMethod]
public async Task TestMethod1()
{
ViewModel vm = new ViewModel();
await vm.MethodAsync();
}
Run Code Online (Sandbox Code Playgroud)
但是,如果您确实希望对实际UI元素进行单元测试,则可以使用Async CTP中包含的类似Windows窗体上下文的类型:
[TestMethod]
public async Task TestMethod1()
{
await WindowsFormsContext.Run(async () =>
{
Control c = new Control();
await Task.Delay(1);
});
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
332 次 |
| 最近记录: |