RxSwift TestScheduler не работает, если подписаться на фоне

У меня есть фиктивный интерактор и маршрутизатор для модульных тестов по методике презентатора:

private func presenterMethod(_ isOn: Bool) -> Driver<Bool> {
    return interactor.interactorMethod(isOn)
        .subscribeOn(ConcurrentDispatchQueueScheduler(qos: .background))
        .observeOn(MainScheduler.instance)
        .do(onError: { [weak self] error in
            self?.view.showError(error)
        })
        .asDriver(onErrorJustReturn: !isOn)
}

И проверить

func testPresenterMethod() {
    let trigger = self.scheduler.createHotObservable([
        next(100, (false)),
        next(200, (true)),
        next(300, (false))
        ]).asDriverOnErrorJustComplete()

    let observer = scheduler.createObserver(Bool.self)
    let input = createInput(presenterTrigger: trigger)
    let output = presenter.transform(input)

    scheduler.scheduleAt(0, action: {
        output.presenterMethodOutput.asObservable()
            .subscribe(observer)
            .disposed(by: self.disposeBag)
    })

    scheduler.start()

    let results = observer.events.map {
        $0.value.element
    }

    XCTAssertEqual(results, [false, true, false])
}

И результаты пусты,

Этот тест работает правильно, только когда я удаляю эти строки из PresenterMethod

    .subscribeOn(ConcurrentDispatchQueueScheduler(qos: .background))
    .observeOn(MainScheduler.instance)

Я попытался с XCTestExpectation и выполнить в блоке do(onNext:{}) и получить те же результаты, работать только без подписки на фон. Метод корректно работает на устройстве и симуляторе, PresenterMethod переключается на коммутатор и выдает правильные события. Как этот тест должен быть написан для работы с фоном SubscribeOn?

1 ответ

Решение

Вы действительно хотите, чтобы планировщики были переданы subscribeOn быть настраиваемой переменной на докладчике.

Поскольку тесты лучше выполнять синхронно, передача планировщика тестов гарантирует, что нет необходимости ждать асинхронного выполнения.

struct Presenter {
  let mainScheduler: SchedulerType  
  let backgroundScheduler: SchedulerType

  init(backgroundScheduler: SchedulerType = ConcurrentDispatchQueueScheduler(qos: .background), mainScheduler: SchedulerType = MainScheduler.instance) {
    self.mainScheduler = mainScheduler
    self.backgroundScheduler = backgroundScheduler
  }

  private func presenterMethod(_ isOn: Bool) -> Driver<Bool> {
    return interactor.interactorMethod(isOn)
        .subscribeOn(backgroundScheduler)
        .observeOn(mainScheduler)
        .do(onError: { [weak self] error in
            self?.view.showError(error)
        })
        .asDriver(onErrorJustReturn: !isOn)
    }
}

А потом, при создании докладчика в рамках тестов

let presenter = Presenter(backgroundScheduler: self.scheduler, mainScheduler: self.scheduler)
Другие вопросы по тегам