C# 测试ReactiveCommand异步结果

C# 测试ReactiveCommand异步结果,c#,unit-testing,reactiveui,C#,Unit Testing,Reactiveui,我使用Xamarin和ReactiveUI做移动应用 我想测试我的ViewModel及其ReactiveCommand 我注册了一个异步操作,该操作在ReactiveCommand中返回一个IObservable 在视图模型中构造函数: Login = new ReactiveCommand(); var loginResult = Login.RegisterAsync(_ => Client.Login(Username, Password)); loginResult.Observe

我使用Xamarin和ReactiveUI做移动应用

我想测试我的
ViewModel
及其
ReactiveCommand

我注册了一个异步操作,该操作在
ReactiveCommand
中返回一个IObservable

视图模型中
构造函数:

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;
    });
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);
[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 :(
}
客户端中有什么。登录::

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;
    });
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);
[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 :(
}
如何测试
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;
    });
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);
[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 :(
}
测试失败,因为断言是在命令完成执行之前作出的

分辨率

我订阅了
Login
命令,并假设我的“断开连接块”将在
RegisterAsync
的块之前调用。这两种方法可以解决问题,或者简单地将“断开”逻辑放在
RegisterAsync
中,如下所示:

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

'解决方案也是必要的。

TaskPoolScheduler
未设置为
调度程序。立即的
,因此它实际上是在后台运行的。试试这个:

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

也可以从输出窗口添加日志。通常情况下,我希望ser ReactiveUI告诉您,检测到测试时,它会将其调度设置为立即。它似乎正确地安排了工作顺序(我使用一些断点进行了检查,并以正确的顺序触发了这些断点),但在断言之前不会绑定到ConnectedUser。执行Login命令后,ConnectedUser将保持null。