iOS RxSwift - testing with RxTest and TestScheduler does not end / terminate test case

2.2k Views Asked by At

I'm trying to understand how to correctly use TestScheduler from RxTest 4.2 for RxSwift 4.2.

How do I correctly create TestScheduler and pass it events which would terminate the scheduler after all events are executed?

The code below goes into infinite loop upon starting the test scheduler. Because it keeps looping synchronously, I have no opportunity to stop the scheduler from the test

    var testScheduler: TestScheduler = TestScheduler(initialClock: 0)

    let stateObserver = testScheduler.createObserver(Bool.self)
    subject.outputRelay.bind(to: stateObserver).disposed(by: bag)

    let events = [next(1,true), next(10,false)]
    let hotObservable = testScheduler.createHotObservable(events)

    //direct events to the given relay
    hotObservable.bind(to: subject.inputRelay).disposed(by: bag)

    testScheduler.start() //infinite loop

//do not get called
    XCTAssertEqual(stateObserver.events, [next(0, InterfaceState.started)])
    testScheduler.stop()

I've narrowed the issued down to this method call within TestScheduler. It seems there's something wrong with the subscription disposal

 func findNext() -> VirtualSchedulerItem<VirtualTime>? {
        while let front = _schedulerQueue.peek() {
            if front.isDisposed {
                //this never gets called
                _schedulerQueue.remove(front)
                continue
            }

            return front
        }

        return nil
    }
1

There are 1 best solutions below

0
On

What I do in this cases is schedule a block in specific time that I know all test should have finish and there stop the subscription. I think in your case should something like this:

//...
let hotObservable = testScheduler.createHotObservable(events)
let disposable = hotObservable.bind(to: subject.inputRelay)
testScheduler.scheduleAt(1) {
     disposable.dispose()
}
testScheduler.start()
XCTAssertEqual(stateObserver.events, [next(0, InterfaceState.started)])
//...