2013-02-23 1 views
0

У меня есть ReactiveAsyncCommand, что на данный момент просто спит на некоторое время:ReactiveUI: Тестирование видимость индикатора прогресса, а ReactiveAsyncCommand выполняет

public ReactiveAsyncCommand SignIn { get; private set; } 

//from constructor: 
SignIn = new ReactiveAsyncCommand(this.WhenAny(x => x.Username, x => x.Password, 
                (u, p) => 
                !string.IsNullOrWhiteSpace(u.Value) && 
                !string.IsNullOrWhiteSpace(p.Value))); 

SignIn.RegisterAsyncAction(_ => Thread.Sleep(4000)); 

Я хочу, чтобы показать индикатор прогресса пока команда выполняется, так что я сделал свойство связывать его видимость против:

private ObservableAsPropertyHelper<bool> _Waiting; 
public bool Waiting 
{ 
    get { return _Waiting.Value; } 
} 

//from constructor: 
_Waiting = SignIn.ItemsInflight 
       .Select(x => x > 0) 
       .ToProperty(this, x => x.Waiting); 

Так, несмотря на то, что, кажется, работает на практике, я хотел бы модульное тестирование показывает, что ожидания ВСЕГДА будет верно в то время как команда выполняется, и только тогда.

Я прочитал this blogpost about the testscheduler, но изо всех сил стараюсь использовать его.

[TestMethod] 
    public void flag_waiting_while_signing_in() 
    { 

     (new TestScheduler()).With(scheduler => 
      { 
       var vm = new SignInViewModel {Username = "username", Password = "password"}; 

       vm.SignIn.Execute(null); 

       Assert.IsTrue(vm.Waiting); 
      }); 
    } 

Этот тест не выполняется (ожидание ложно). Я попытался добавить вызовы к scheduler.start() и scheduler.advanceBy(), но это не имело никакого значения.

Является ли мой подход к тестированию этого неправильно? Если подход прав, что еще не так?

Редактировать
Так что я изменил Thread.Sleep() как было предложено:

SignIn.RegisterAsyncAction(_ => 
      { 
       Observable.Interval(TimeSpan.FromMilliseconds(4000)); 
      }); 

И пытался контролировать время, вызвав scheduler.AdvanceBy(...) перед проверкой Waiting -flag. Тем не менее, не зеленый.

+0

Вы должны использовать RegisterAsyncObservable вместо этого, и указать RxApp.DispatcherScheduler как планировщик для интервала –

+0

я не уверен, я понимаю. Во-первых, с помощью 'RxApp.DispatcherScheduler', вы имеете в виду' RxApp.DeferredScheduler'? Во-вторых, в комментарии выше DeferredScheduler говорится, что этот планировщик используется для рабочих элементов, которые должны запускаться в потоке ui. В конце концов, я хочу, чтобы моя команда signin сделала что-то более полезное. Это идея, что я использую deferredscheduler при unittesting и планировщик задач для реальной работы? В любом случае, тест теперь идет зеленым, но, проверяя, что флаг сброшен после 4-секундной задержки, он снова покраснел. Есть еще предложения? – Vegar

+0

Да, я имел в виду DeferredScheduler, хотя вы правы, более реалистично использовать TaskPoolScheduler (и вы получите тот же результат!) –

ответ

1

Причина, по которой TestScheduler падает, заключается в том, что у вас есть источник асинхронности, который находится вне представления TestScheduler - Thread.Sleep. Нет никакого способа, чтобы он мог контролировать это, он будет всегда займет 4 реальных секунды. Заменить его с Observable.Interval вместо этого и он должен работать, как вы ожидаете

[TestMethod] 
public void flag_waiting_while_signing_in() 
{ 

    (new TestScheduler()).With(scheduler => 
     { 
      var vm = new SignInViewModel {Username = "username", Password = "password"}; 

      vm.SignIn.Execute(null); 

      scheduler.AdvanceBy(TimeSpan.FromMilliseconds(2000)); 
      Assert.IsTrue(vm.Waiting); 

      // Move past the end 
      scheduler.AdvanceBy(TimeSpan.FromMilliseconds(5000)); 
      Assert.IsFalse(vm.Waiting); 
     }); 
} 
+0

Это звучит разумно, но тест по-прежнему не удается. Немного изменил вопрос. – Vegar

+0

Как уже упоминалось в моем комментарии к вопросу, последнее утверждение терпит неудачу. – Vegar

Смежные вопросы