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

时间:2019-06-25 06:11:11

标签: swift rx-swift 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内部创建了一个发布主题,以通知视图何时应显示加载器。

一切正常,除了我不知道如何使用RxTest框架进行测试。

我试图使用调度程序和冷观测器,但无法使其正常工作。

我想拥有的东西

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

也许,isLoading是我做的方式,这是不可测试的。但看来它正在通过输出解决,我认为也许有某种方法。

非常感谢您,如果不清楚,请随时进行编辑或指导我提出更好的问题。非常感谢。

1 个答案:

答案 0 :(得分:1)

几件事:

您的Input结构应包含可观察对象,而不是主题。这样,您就可以正确地附加它们。

您不想使用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)
    }
}