2012-07-04 13 views
5

我需要測試單元測試的IObservable <T>與ObserveOnDispatcher

 var watcher = new FakeIFileSystemWatcher(); 
     watcher.FilesToBeImported 
      .ObserveOnDispatcher() 
      .Subscribe(list.Add); 

所以我創造了這個小單元測試的代碼,但我不能讓它通過的原因list.Count始終爲0

[Test] 
    public void Foo() 
    { 
     var list = new List<string>(); 

     var watcher = new FakeIFileSystemWatcher(); 
     watcher.FilesToBeImported 
      .ObserveOnDispatcher() 
      .Subscribe(list.Add); 

     Task task = Task.Factory.StartNew(() => 
     {     
      watcher.AddFile("cc"); 
      watcher.AddFile("cc"); 
      watcher.AddFile("cc"); 
     }, TaskCreationOptions.LongRunning); 
     Task.WaitAll(task); 

     Assert.AreEqual(3, list.Count); 
    } 

如果我註釋掉方法

  .ObserveOnDispatcher() 

它通過但我怎麼可以得到它也正在與觀察OnDispatcher()?

+0

'list.Count的值是什麼'在失敗? –

+0

我解決了使用類DispatcherUtil我在這裏找到 http://stackoverflow.com/questions/1106881/using-the-wpf-dispatcher-in-unit-tests – jitidea

+0

我只想指出,通過具有併發性(隱式或顯式的)在你的單元測試中,你的能力確實有限。在這裏你有兩個任務和一個調度器,你沒有提供'接縫',你可以用它們替代測試雙(模擬/存根)。就像(我假設)你在你的prod代碼中注入了一個真正的IFileSystemWatcher實現,你會注入一個SchedulerProvider,它爲你提供了prod中的真正concurreny,但是在你的單元測試中測試了調度器。更快的單元測試,更容易測試超時等其他事情。 –

回答

1

我解決了使用類DispatcherUtil我發現這裏 Using the WPF Dispatcher in unit tests

現在我的代碼如下

[Test] 
    public void Foo() 
    { 
     var list = new List<string>(); 

     var watcher = new FakeIFileSystemWatcher(); 
     watcher.FilesToBeImported 
      .ObserveOnDispatcher() 
      .Subscribe(list.Add); 

     Task task = Task.Factory.StartNew(() => 
     { 
      watcher.AddFile("cc"); 
      watcher.AddFile("cc"); 
      watcher.AddFile("cc"); 
      watcher.AddFile("cc"); 
     }, TaskCreationOptions.LongRunning); 
     Task.WaitAll(task); 
     DispatcherUtil.DoEvents(); 
     Assert.AreEqual(4, list.Count); 
    } 

,它就像一個魅力

5

如果你使用ObserveOnDispatcher你創建一個依賴到「調度器」,這意味着你需要一個窗口和一個消息循環。要在單元測試中解決此問題,您可以改爲使用使用調度程序的ObserveOn方法,然後使用依賴注入來注入正確的調度程序。對於單元測試,您可以使用Scheduler.Immediate,對於實際應用,您可以使用DispatcherScheduler.Instance。注意,還有一個TestScheduler這對於在虛擬時間運行單元測試非常有用。

+0

感謝您的回覆。 這行代碼watcher.FilesToBeImported.ObserveOnDispatcher()。Subscribe(list.Add); 在我的系統中,所以我不能僅僅爲了測試而改變它 – jitidea

+3

@ scott4dev:我的觀點是,你有時必須修改你的被測系統,使它成爲單元可測試的。例如。如果您訪問數據庫,則必須爲數據庫創建一個接口,以允許您存儲數據庫訪問等。當然,您的解決方案會避免這種情況。 –

+0

你是對的,有時必須修改你的被測系統,使其成爲單元可測試的,但在我看來這並非如此。我更喜歡使用DispatcherUtil.DoEvents();在我的測試中讓我的SUT處於原始狀態 – jitidea

0

你可以嘗試調用你的方法一樣這個:

var dispatcher = Application.Current != null ? Application.Current.Dispatcher : Dispatcher.CurrentDispatcher; 

dispatcher.Invoke((Action)(() => YourMethodToTest());