ReactiveUI: Testing progress indicator visibility while ReactiveAsyncCommand executes

谁说我不能喝 提交于 2019-12-10 11:56:03

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!