Question

I use Xamarin and ReactiveUI to do mobile apps.

I'd like to test my ViewModel and its ReactiveCommand.

I register an asynchronous operation which return an IObservable inside the ReactiveCommand.

In ViewModel constructor :

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 :

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 ? 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. Inverted the two would resolve the issue or simply put the "disconnection" logic inside RegisterAsync like this :

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

Paul Betts ' solution was also necessary.

Was it helpful?

Solution

TaskPoolScheduler is not set to Scheduler.Immediate, so it really is running in the background. Try this:

Scheduler.CurrentThread.With(sched => {
    // TODO: Write your code here, now both schedulers are
    // rigged to CurrentThread.
});
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top