触发一个事件并等待多个事件 RxTest

Trigger an event and wait for multiple events 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)
    }
}

我在 viewModel 中创建了一个 Publish Subject 来通知视图何时应该显示加载器。

一切正常,只是我不知道如何使用 RxTest 框架对其进行测试。

我尝试使用调度程序和冷可观察对象,但无法使其正常工作。

我想要的:

  1. 使用调度程序将 .next(10, ()) 发送到触发器。
  2. 以某种方式记录 isLoading 的事件并断言先为真然后为假的相等。像这样:[.next(10, true), .next(20, false)].

也许,我做的isLoading,它是不可测试的。但似乎它正在通过输出输出,我想也许有一些方法。

非常感谢,如果有什么不清楚的地方,请随时编辑或指导我提出更好的问题。非常感谢。

几件事:

您的 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)
    }
}