2012-08-30 97 views
0

我已經將我的代碼移植到WinRT和Rx的RTM版本。我在我的ViewModels中使用ReactiveUI。在移植代碼之前,我的單元測試運行沒有問題,但現在我得到了一個奇怪的行爲。使用Rx RTM觀察命令和單元測試

這裏測試:

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

如果我調試一步的測試步驟,斷言是失敗,但使用測試運行它的失敗......

收集斷言是通過訂閱該命令的方法修改:

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

該代碼在將其移動到RTM之前正在工作。我也嘗試刪除ObserveOn,並在Assert之前添加await Task.Delay(),但未成功。

回答

3

Steven的答案是正確的,但缺少一些RxUI特定的東西。這與測試運行器中的調度無關,但原因是WinRT版本的ReactiveUI目前無法正確檢測它是否在測試運行器中。

現在裝聾作啞的解決方法是設置這在所有測試的頂部:

RxApp.DeferredScheduler = Scheduler.CurrentThread; 

使用TestScheduler每一個測試,這是矯枉過正,實際上是不能與某些類型的兼容的測試。 TestScheduler適用於模擬時間流逝的測試。

1

您的問題是MSTest單元測試有一個默認SynchronizationContext。因此ObserveOnReactiveAsyncCommand將編組到線程池而不是WPF上下文。這導致競爭條件。

您的第一個也是最好的選擇是Rx TestScheduler

另一個選項是await一些完成信號(並確保您的測試方法是async Task而不是async void)。

否則,如果您只需要SynchronizationContext,則可以使用AsyncContext from my AsyncEx library在您自己的SynchronizationContext中執行測試。

最後,如果您有任何直接使用Dispatcher而不是SynchronizationContext的代碼,則可以使用異步CTP下載中的WpfContext

+0

感謝Stephen的回答。我將在明天進行測試,但是我在WinRT上,所以WPF相關的解決方案不是一種選擇。 TestScheduler似乎很有前途。 – MatthieuGD

+0

'WpfContext' - 儘管名稱 - 只是使用Dispatcher,我相信它適用於SL,所以我期望它可以用於WinRT。 –