Модель представления модульного тестирования, которая использует SelectMany для вызова асинхронного метода в ReactiveUI.

Я новичок в ReactiveUI и пытаюсь протестировать модель представления, которая выглядит так:

public interface IService
{
    Task<SessionModel> GetData(string id);
}

/// Provides a group of schedulers available to be used
public interface ISchedulers
{
    IScheduler Default { get; }
    IScheduler Dispatcher { get; }
}

public class MyVm : ReactiveObject
{
    IService service;

    public MyVm(ISchedulers schedulers, IService service)
    {
        this.service = service;
        this.session = this.WhenAnyValue(x => x.SessionId)
                           .SelectMany(SearchSession)
                           .ObserveOn(schedulers.Default)
                           .ToProperty(this, x => x.Session);
    }

    private async Task<SessionModel> SearchSession(string id)
    {
        return await this.service.GetData(id);
    }

    private string sessionId;
    public string SessionId
    {
        get => sessionId;
        set => this.RaiseAndSetIfChanged(ref sessionId, value);
    }


    readonly ObservableAsPropertyHelper<SessionModel> session;
    public SessionModel Session
    {
        get { return session.Value; }
    }

}

public class SessionModel { }

Я издеваюсь над служебным вызовом, чтобы вернуть фиктивные данные, но не уверен, что мне нужно сделать с TestScheduler, чтобы заставить SelectMany работать.

Вот тестовый класс, который показывает, как я могу создать тест для модели представления. Цель состоит в том, чтобы в конечном итоге проверить, что модель установлена:

[TestClass]
public class MyVmTests
{
    [TestMethod]
    public void CreateClass
    {
       var subject = new MyVm(/*pass in mocks*/);

       subject.SessionId="test";

       Assert.IsNotNull(subject.Session);
     }
}

person cliff    schedule 23.10.2018    source источник
comment
Что такое ISchedulers?   -  person Shlomo    schedule 23.10.2018
comment
он предоставляет список возможных планировщиков для использования наблюдаемым. В тесте высмеивается возврат TestScheduler. в реальном коде он возвращает System.Reactive.Concurrency.Scheduler.Default.   -  person cliff    schedule 23.10.2018
comment
Я обновил ваш код вещами, которые, как я полагаю, у вас есть. Можете ли вы добавить то, что вы пытаетесь протестировать?   -  person Shlomo    schedule 23.10.2018
comment
добавлен тестовый класс.   -  person cliff    schedule 23.10.2018
comment
я не могу добавить больше кода, не добавляя больше слов. Просто обратите внимание, что SessionId будет правильно определен для использования RaiseAndSetIfChanged   -  person cliff    schedule 23.10.2018
comment
Да, только что понял, что это не так.   -  person Shlomo    schedule 23.10.2018


Ответы (1)


Я не думаю, что использование TestScheduler необходимо. Для меня проходят следующие передачи (с использованием Moq):

var mockSchedulers = new Mock<ISchedulers>();
mockSchedulers.Setup(s => s.Default).Returns(Scheduler.Immediate);
var id = "123";
var mockService = new Mock<IService>();
var returnSession = new SessionModel();
mockService.Setup(s => s.GetData(It.Is<string>(i => i == id)))
    .ReturnsAsync(returnSession);
var target = new MyVm(mockSchedulers.Object, mockService.Object);

target.SessionId = id;

Assert.IsNotNull(target.Session);
Assert.AreEqual(returnSession, target.Session);

TestScheduler лучше всего подходит, когда вы пытаетесь протестировать что-то со временем (например, задержку, доказывающую, что задержка действительно произошла). Вы действительно не делаете этого здесь.

person Shlomo    schedule 23.10.2018
comment
Хм, проблема в том, что у меня есть класс, который реализует ISchedulers и заставляет все свойства возвращать TestScheduler. Итак, если мне нужно иметь разные макеты IScheduler для каждого теста, чтобы я мог переключаться между Default.Immediate и TestScheduler, как бы вы предложили мне реализовать vm.Session, чтобы в других тестах я мог установить для него значение? - person cliff; 23.10.2018
comment
Не бери в голову. заставил его работать, используя TestScheduler и вызывая Start() после установки идентификатора. Спасибо!! - person cliff; 23.10.2018