问题
I have a ReactiveAsyncCommand that for the moment are just sleeping for a while:
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));
I want to show a progress indicator while the command executes, so I have made a property to bind its visibility against:
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);
So, even though it seems to work in practice, I would love a unit test showing that Waiting allways will be true while the command executes, and only then.
I have read this blogpost about the testscheduler, but struggle to put it to use.
[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);
});
}
This test fails (waiting is false). I have tried to add a calls to scheduler.start()
and scheduler.advanceBy( )
but that didn't make any difference.
Is my approach to testing this wrong? If the approach is right, what else is wrong?
Edit
So I changed the Thread.Sleep()
as suggested:
SignIn.RegisterAsyncAction(_ =>
{
Observable.Interval(TimeSpan.FromMilliseconds(4000));
});
And tried to control time by calling scheduler.AdvanceBy(...)
before checking the Waiting
-flag. Still no green, though.
回答1:
The reason that TestScheduler is falling over, is that you have a source of asynchrony that is outside TestScheduler's view - the Thread.Sleep
. There's no way that it can control it, it will always take up 4 real seconds. Replace it with an Observable.Interval
instead and it should work as you expect
[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);
});
}
来源:https://stackoverflow.com/questions/15047124/reactiveui-testing-progress-indicator-visibility-while-reactiveasynccommand-exe