2015-10-19 40 views
2

我試圖單元測試視圖模型時遇到問題,該模型使用WhenAnyValue來偵聽屬性中的更改,並根據屬性的新值填充列表。由於與第三方軟件進行交互時,我需要使用ThrottleReactiveUI - 使用節流閥測試訂閱

我的解決方案在生產環境中工作,但我的單元測試遇到了一些麻煩。這似乎與沒有讓測試計劃程序正確前進有關,因此實際運行油門後的訂閱。我已經創建了我的問題的簡化版本,我希望能夠說明問題。

視圖模型來測試

public class ViewModel : ReactiveObject 
{ 

    public ViewModel(IScheduler scheduler) 
    { 
     ListToBeFilled = new List<int>(); 

     this.WhenAnyValue(vm => vm.SelectedValue) 
      .Throttle(TimeSpan.FromMilliseconds(500), scheduler) 
      .Skip(1) 
      .Subscribe(value => 
      { 
       // Do a computation based on value and store result in 
       // ListToBeFilled. 
       ListToBeFilled = new List<int>() {1, 2, 3}; 
      }); 

    } 

    private string _selectedValue; 
    public string SelectedValue 
    { 
     get { return _selectedValue; } 
     set { this.RaiseAndSetIfChanged(ref _selectedValue, value); } 
    } 

    public List<int> ListToBeFilled { get; set; } 
} 

視圖模型試驗

[TestFixture] 
[RequiresSTA] 
public class ViewModelTests 
{ 
    [Test] 
    public void TestViewModel() 
    { 
     // Arrange 
     (new TestScheduler()).With(scheduler => 
     { 
      ViewModel vm = new ViewModel(scheduler); 

      // Act 
      vm.SelectedValue = "test value"; 
      scheduler.AdvanceByMs(1000); 

      // Assert 
      Assert.AreEqual(3, vm.ListToBeFilled.Count); 
     }); 
    } 
} 

測試失敗說預計:3不過是0。在不使用Throttle(我需要讓事情在生產中工作)運行測試時,測試通過。我是否使用測試計劃程序錯誤?爲了消耗節流閥,我需要做些什麼?

回答

4

您的代碼(幾乎)完全正確,但您被WhenAnyValue/Skip行爲欺騙。

WhenAnyValue將發佈您嘗試跳過的初始值(空),使用Skip。但由於Throttle正在TestScheduler上運行,因此在您有效啓動調度程序(AdvanceBy)之前,跳過將不會被觸發,此時2個更改將排隊(null和"test value"),但Throttle將丟棄第一個,並且Skip第二個一個,因此你的訂閱代碼將永遠不會被調用。

的方法很多解決這個問題:

  1. 設置測試值前添加scheduler.AdvanceByMs(1000);(將確保初始值被傳播)

  2. 移動SkipThrottle之前(不需要調度,因此將立即適用)

(後者可能是更好的,因爲你的代碼是錯誤的認爲在視圖模型創建後500毫秒內不會得到選擇,這不太可能,但也不是完全不可能的)