1

这是我第一次使用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 方式,它是不可测试的。但似乎它正在通过输出输出,我认为也许有某种方式。

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

4

1 回答 1

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

于 2019-06-25T15:59:49.860 回答