我已将我的代码移植到WinRT和Rx的RTM版本。我在ViewModels中使用ReactiveUI。在移植代码之前,我的单元测试运行没有问题,但现在我有一个奇怪的行为。
这里测试:
var sut = new MyViewModel();
myViewModel.MyCommand.Execute(null) //ReactiveAsyncCommand
Assert.AreEqaul(0, sut.Collection.Count)
如果我逐步调试测试,断言不失败,但使用测试运行器失败...
声明的Collection由订阅命令的方法修改:
MyCommand.RegisterAsyncTask(_ => DoWork())
.ObserveOn(SynchronizationContext.Current)
.Subscribe(MethodModifyingCollection);
在将代码移至RTM之前,代码正在运行。我还尝试删除ObserveOn
并在Assert之前添加await Task.Delay()
但没有成功。
答案 0 :(得分:3)
现在的愚蠢解决方法是将其设置在所有测试的顶部:
RxApp.DeferredScheduler = Scheduler.CurrentThread;
不对每个测试使用TestScheduler,它是过度的,实际上与某些类型的测试不兼容。 TestScheduler适用于模拟时间流逝的测试。
答案 1 :(得分:1)
您的问题是MSTest单元测试具有默认SynchronizationContext
。因此ObserveOn
和ReactiveAsyncCommand
将封送到线程池而不是WPF上下文。这会导致竞争状态。
您的第一个也是最好的选择是Rx TestScheduler
。
另一种选择是await
一些完成信号(确保您的测试方法为async Task
,而不是async void
)。
否则,如果您只需要SynchronizationContext
,则可以使用AsyncContext
from my AsyncEx library在自己的SynchronizationContext
内执行测试。
最后,如果您有任何代码直接使用Dispatcher
代替SynchronizationContext
,您可以使用Async CTP下载中的WpfContext
。