【问题标题】:ReactiveUI: Testing progress indicator visibility while ReactiveAsyncCommand executesReactiveUI:在 ReactiveAsyncCommand 执行时测试进度指示器的可见性
【发布时间】:2013-02-25 07:56:17
【问题描述】:

我有一个 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));
            });

并尝试通过在检查Waiting 标志之前调用scheduler.AdvanceBy(...) 来控制时间。不过还是没有绿色。

【问题讨论】:

  • 您需要改用RegisterAsyncObservable,并指定RxApp.DispatcherScheduler作为Interval的调度器
  • 我不确定我是否理解。首先,RxApp.DispatcherScheduler 是指RxApp.DeferredScheduler 吗?其次,在 DeferredScheduler 上面的评论中,它说这个调度器用于应该在 ui 线程上运行的工作项。最终,我希望我的登录命令做一些更有用的事情。我在单元测试时使用 deferredscheduler 并在实际工作中使用任务池调度程序的想法是什么?无论如何,测试现在变绿了,但是通过检查标志在 4 秒延迟后重置,它又变红了。还有什么建议吗?
  • 是的,我的意思是 DeferredScheduler,虽然你是对的,但使用 TaskPoolScheduler 更现实(你会得到相同的结果!)

标签: system.reactive reactiveui


【解决方案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); 
        });
}

【讨论】:

  • 这听起来很合理,但测试仍然失败。稍微更新了问题。
  • 正如我在对该问题的评论中提到的,最后一个断言失败了。
猜你喜欢
  • 1970-01-01
  • 2018-12-17
  • 2018-04-11
  • 2015-05-19
  • 1970-01-01
  • 2011-10-17
  • 1970-01-01
  • 2020-02-06
  • 1970-01-01
相关资源
最近更新 更多