Запустить событие и ждать нескольких событий RxTest
Я впервые использую RxTest, и я изо всех сил пытаюсь сделать следующий подход:
protocol ViewModelType {
func transform(input: ViewModel.Input) -> ViewModel.Output
}
struct ViewModel: ViewModelType {
private let isLoading = PublishSubject<Bool>()
struct Input {
let trigger: PublishSubject<Void>
}
struct Output {
let someAction: Observable<Void>
let isLoading: Observable<Bool>
}
func transform(input: Input) -> Output {
let someAction = input
.trigger
.do(onNext: { _ in
self.isLoading.onNext(true)
//do some async task
self.isLoading.onNext(false)
})
return Output(someAction: someAction, isLoading: isLoading)
}
}
Я создал Subject Subject внутри viewModel, чтобы уведомить представление, когда оно должно показывать загрузчик или нет.
Все работает отлично, за исключением того, что я не знаю, как проверить это с помощью инфраструктуры RxTest.
Я пытался использовать планировщик и холодные наблюдаемые, но не смог заставить его работать.
Что бы я хотел иметь:
- С помощью планировщика отправьте.next(10, ()) в триггер.
- Каким-то образом запишите события isLoading и assert равные, которые сначала будут истинными, а затем ложными. Вот так: [.next(10, true), .next(20, false)].
Может быть, isLoading, как я это сделал, не поддается проверке. Но, кажется, он проходит через вывод, я думаю, может быть, есть какой-то путь.
Большое спасибо, если что-то неясно, пожалуйста, не стесняйтесь редактировать или направить меня к лучшему вопросу. Очень признателен.
1 ответ
Пара вещей:
Твой Input
Структура должна содержать Observables, а не предметы. Таким образом, вы можете прикрепить к ним правильно.
Вы не хотите использовать do
оператор. Вместо этого сначала подумайте о проблеме из выходных данных. Когда срабатывает триггер, вы хотите, чтобы isLoading излучал true, и вы хотите, чтобы асинхронная задача запускалась. Это означает, что у вас должно быть две наблюдаемые цепочки. Там много примеров кода, показывающих, как это сделать.
А пока вот ваш тест (вместе с необходимыми изменениями в вашем коде:
class RxSandboxTests: XCTestCase {
func testOne() {
let scheduler = TestScheduler(initialClock: 0)
let trigger = scheduler.createHotObservable([.next(10, ())])
let someActionResult = scheduler.createObserver(Bool.self)
let isLoadingResult = scheduler.createObserver(Bool.self)
let bag = DisposeBag()
let sut = ViewModel()
let input = ViewModel.Input(trigger: trigger.asObservable())
let output = sut.transform(input: input)
bag.insert(
output.someAction.map { true }.bind(to: someActionResult),
output.isLoading.bind(to: isLoadingResult)
)
scheduler.start()
XCTAssertEqual(someActionResult.events, [.next(10, true)])
XCTAssertEqual(isLoadingResult.events, [.next(10, true), .next(10, false)])
}
}
protocol ViewModelType {
func transform(input: ViewModel.Input) -> ViewModel.Output
}
struct ViewModel: ViewModelType {
private let isLoading = PublishSubject<Bool>()
struct Input {
let trigger: Observable<Void>
}
struct Output {
let someAction: Observable<Void>
let isLoading: Observable<Bool>
}
func transform(input: Input) -> Output {
let someAction = input
.trigger
.do(onNext: { _ in
self.isLoading.onNext(true)
//do some async task
self.isLoading.onNext(false)
})
return Output(someAction: someAction, isLoading: isLoading)
}
}