0

我已将我的代码移植到 WinRT 和 Rx 的 RTM 版本。我在我的 ViewModel 中使用 ReactiveUI。在移植代码之前,我的单元测试运行没有问题,但现在我有一个奇怪的行为。

这里是测试:

var sut = new MyViewModel();
myViewModel.MyCommand.Execute(null) //ReactiveAsyncCommand
Assert.AreEqaul(0, sut.Collection.Count)

如果我一步一步调试测试,断言并没有失败,但是使用测试运行器它失败了......

断言的集合由订阅命令的方法修改:

MyCommand.RegisterAsyncTask(_ => DoWork())
            .ObserveOn(SynchronizationContext.Current)
            .Subscribe(MethodModifyingCollection);

该代码在将其移至 RTM 之前正在运行。我还尝试在 Assert 之前删除ObserveOn并添加一个,但没有成功。await Task.Delay()

4

2 回答 2

3

Steven 得到了正确的答案,但是缺少一些 RxUI 特定的东西。这肯定与在测试运行器中的调度有关,但原因是 WinRT 版本的 ReactiveUI 目前无法正确检测它是否在测试运行器中。

现在愚蠢的解决方法是将其设置在所有测试的顶部:

RxApp.DeferredScheduler = Scheduler.CurrentThread;

不要在每个测试中使用 TestScheduler,这太过分了,实际上与某些类型的测试不兼容。TestScheduler 适用于模拟时间流逝的测试。

于 2012-08-30T19:16:17.473 回答
1

您的问题是 MSTest 单元测试有一个默认的SynchronizationContext. 因此ObserveOnReactiveAsyncCommand并将编组到线程池而不是 WPF 上下文。这会导致竞争条件。

您的第一个也是最好的选择是RxTestScheduler

另一种选择是await一些完成信号(并确保您的测试方法是async Task,不是async void)。

否则,如果您只需要一个SynchronizationContext,您可以使用AsyncContext我的 AsyncEx 库在您自己的SynchronizationContext.

最后,如果您有任何代码直接使用Dispatcher而不是SynchronizationContext,您可以WpfContext从 Async CTP 下载中使用。

于 2012-08-30T01:31:07.720 回答