简体   繁体   English

测试ReactiveCommand异步结果

[英]Testing ReactiveCommand async result

I use Xamarin and ReactiveUI to do mobile apps. 我使用Xamarin和ReactiveUI来做移动应用程序。

I'd like to test my ViewModel and its ReactiveCommand . 我想测试我的ViewModel及其ReactiveCommand

I register an asynchronous operation which return an IObservable inside the ReactiveCommand . 我注册了一个异步操作,它返回ReactiveCommand的IObservable。

In ViewModel constructor : ViewModel构造函数中:

Login = new ReactiveCommand();
var loginResult = Login.RegisterAsync(_ => Client.Login(Username, Password));
loginResult.ObserveOn(RxApp.MainThreadScheduler).BindTo(this, self => self.ConnectedUser);
Login
    .Where(_ => ConnectedUser != null)
    .Subscribe(_ => {
        ConnectedUser.Disconnect();
        ConnectedUser = null;
    });

What's in Client.Login : Client.Login什么:

return Observable.Start(async () => {
    // Do an HTTP POST to login the user, with await stuff in
    // Return the User on success or throw an exception on error
}, RxApp.TaskpoolScheduler)
.Select(task => task.Result);

How to test the ViewModel login success ? 如何测试ViewModel登录成功? Here is my approach which doesn't work : 这是我的方法不起作用:

[Test]
public void TestLoginSuccess()
{
    ViewModel viewModel = new ViewModel();
    viewModel.Username = "toto";
    viewModel.Password = "****";

    viewModel.Login.Execute(null);

    Assert.That(viewModel.ConnectedUser, Is.Not.Null); // always null so fail :(
}

The test fails because the assertion is made before the command has finished executing. 测试失败,因为断言是在命令执行完之前完成的。

Resolution 解析度

I was subscribing to the Login command and assumed that my "disconnection block" would be called before the RegisterAsync 's one. 我订阅了Login命令并假设我的“断开块”将在RegisterAsync之前被调用。 Inverted the two would resolve the issue or simply put the "disconnection" logic inside RegisterAsync like this : 反过来两个会解决问题或简单地将“断开”逻辑放在RegisterAsync如下所示:

var loginResult = Login.RegisterAsync(_ => {
    if (ConnectedUser != null)
    {
        ConnectedUser.Disconnect();
        ConnectedUser = null;
    }
    Client.Login(Username, Password);
});

Paul Betts ' solution was also necessary. Paul Betts的解决方案也是必要的。

TaskPoolScheduler is not set to Scheduler.Immediate , so it really is running in the background. TaskPoolScheduler未设置为Scheduler.Immediate ,因此它确实在后台运行。 Try this: 尝试这个:

Scheduler.CurrentThread.With(sched => {
    // TODO: Write your code here, now both schedulers are
    // rigged to CurrentThread.
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM