Тестирование асинхронного результата ReactiveCommand

Я использую Xamarin и ReactiveUI для создания мобильных приложений.

Я хотел бы проверить свой ViewModel и его ReactiveCommand.

Я регистрирую асинхронную операцию, которая возвращает IObservable внутри ReactiveCommand.

В конструкторе 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 также было необходимо.


person nverinaud    schedule 25.10.2013    source источник
comment
Можете ли вы также добавить журнал из окна вывода. Обычно я ожидаю, что ser ReactiveUI сообщит вам, что его планирование установлено сразу после обнаружения тестирования.   -  person AlSki    schedule 25.10.2013


Ответы (1)


TaskPoolScheduler не установлен в Scheduler.Immediate, поэтому он действительно работает в фоновом режиме. Попробуй это:

Scheduler.CurrentThread.With(sched => {
    // TODO: Write your code here, now both schedulers are
    // rigged to CurrentThread.
});
person Ana Betts    schedule 26.10.2013
comment
Кажется, правильно последовательность работы (я проверил с помощью некоторых точек останова, и они срабатывают в правильном порядке), но привязка к ConnectedUser не выполняется до утверждения. ConnectedUser остается нулевым после выполнения команды входа в систему. - person nverinaud; 28.10.2013