2017-04-15 11 views
2

私はReactiveUIを利用してライブラリについての感想を得るために書きましたWPF-Appを書き直しています。スケジューラ/スロットルをテストするのに推奨される方法

私はこれまでのところ本当に好きです!

今私はThrottleメソッドを見つけて、コレクションにフィルタを適用するときに使いたいと思っています。

これは私のViewModelです:

namespace ReactiveUIThrottle 
{ 
    public class MainViewModel : ReactiveObject 
    { 
     private string _filter; 

     public string Filter { get => _filter; set => this.RaiseAndSetIfChanged(ref _filter, value); } 

     private readonly ReactiveList<Person> _persons = new ReactiveList<Person>(); 

     private readonly ObservableAsPropertyHelper<IReactiveDerivedList<Person>> _filteredPersons; 

     public IReactiveDerivedList<Person> Persons => _filteredPersons.Value; 
     public MainViewModel() 
     { 
      Filter = string.Empty; 
      _persons.AddRange(new[] 
      { 
       new Person("Peter"), 
       new Person("Jane"), 
       new Person("Jon"), 
       new Person("Marc"), 
       new Person("Heinz") 
      }); 

      var filterPersonsCommand = ReactiveCommand.CreateFromTask<string, IReactiveDerivedList<Person>>(FilterPersons); 

      this.WhenAnyValue(x => x.Filter) 
       // to see the problem 
       .Throttle(TimeSpan.FromMilliseconds(2000), RxApp.MainThreadScheduler) 
       .InvokeCommand(filterPersonsCommand); 

      _filteredPersons = filterPersonsCommand.ToProperty(this, vm => vm.Persons, _persons.CreateDerivedCollection(p => p)); 


     } 
     private async Task<IReactiveDerivedList<Person>> FilterPersons(string filter) 
     { 
      await Task.Delay(500); // Lets say this takes some time 
      return _persons.CreateDerivedCollection(p => p, p => p.Name.Contains(filter)); 
     } 
    } 
} 

GUIを使用している場合、フィルタリング自体は、スロットリングも、魔法のように動作します。

しかし、私はフィルタリングの動作をunittestのしたい、これが私の最初の試みである:

[Test] 
    public void FilterPersonsByName() 
    { 
     var sut = new MainViewModel(); 

     sut.Persons.Should().HaveCount(5); 
     sut.Filter = "J"; 
     sut.Persons.Should().HaveCount(2); 
    } 

コレクションはまだ5人を持っているので、このテストが失敗しました。

await Task.Delay(500)FilterPersonsで取り除くと、テストは合格しますが、スロットルから2秒かかります。

1)ユニットテストをスピードアップするために、テスト中にスロットルを瞬時にする方法はありますか?

2)フィルタの非同期動作をテストするにはどうすればよいですか?

私はReactiveUI 7.xのに

答えて

2

ショート答え使用しています:

  1. はい、テストで実行するとき、あなたがCurrentThreadScheduler.Instanceを使用していることを確認すること
  2. 代わりのCurrentThreadSchedulerを使用することにより、TestSchedulerを使用します手動で前進させてください。

もっと長い答えは、あなたのユニットテストが制御できることです彼はあなたのシステムUnder Test(SUT)によって使用されているスケジューラーです。デフォルトでは、通常はCurrentThreadScheduler.Instanceを使用して、スケジューラを手動で進める必要なしに「即座に」実行されるようにします。しかし、タイミングを検証するテストを作成する場合は、代わりにTestSchedulerを使用します。あなたは、あなたがRxApp.*Schedulerを使用しているように見えるとして、このように使用することができますWith拡張メソッド、を見て、場合

私はRxApp周囲のコンテキストを使用して避ける傾向にありますまったく同じ理由で私は周囲の文脈をすべて避けます:彼らは状態を共有し、結果としてトラブルを引き起こす可能性があります。代わりに、IScheduler(または2つ)を私のSUTに依存関係として注入します。

+0

ご回答いただきありがとうございます。プロダクションコードとして実行しているときに、モデルに何を注入しますか? 'RxApp.MainThreadScheduler'? –

+0

更新: [テスト] 公共ボイドFilterPersonsByName(){ 新しいTestScheduler()(schedの=> { するvar SUT =新しいMainViewModel(SCHED)で、 がschedの。AdvanceByMs(3000); sut.Persons.Should()。HaveCount(5); sut.Filter = "J"; sched.AdvanceByMs(3000); sut.Persons.Should()。HaveCount(2); }); } が動作します。 2番目のポイントはworkign outです:-)私は 'CurrentThreadScheduler.Instace'を与えても即座に実行されるのではなく、2〜3秒で実行されます –

+0

あなたが好きなのなら、実行時に' RxApp'スケジューラーを使うことができます。個人的には、スケジューラを自分で作成して注入しますが、それは個人的な好みであり、必要ではありません。 –

関連する問題