我使用Xamarin和ReactiveUI来制作移动应用。
我想测试我的ViewModel
及其ReactiveCommand
。
我注册了一个异步操作,它返回ReactiveCommand
内的IObservable。
在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;
});
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);
如何测试ViewModel
登录成功?这是我的方法不起作用:
[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);
});
Paul Betts'解决方案也是必要的。
答案 0 :(得分:2)
TaskPoolScheduler
未设置为Scheduler.Immediate
,因此它确实在后台运行。试试这个:
Scheduler.CurrentThread.With(sched => {
// TODO: Write your code here, now both schedulers are
// rigged to CurrentThread.
});