override func setUp() {
super.setUp()
scheduler = TestScheduler(initialClock: 0)
disposeBag = DisposeBag()
SharingScheduler.mock(scheduler: scheduler) {
viewModel = MetronomeViewModel()
I have read about it over here: RxTest - How to test the Observable in Swift - Code in a suit
(before it was driveOnScheduler(testScheduler) but now it’s deprecated)
Hey there! Excellent question.
I want to start off with the fact that, we unfortunately as authors can’t cover 100% of the information in a single tutorial, but this is a great piece to talk about, so let me expand a bit, and sorry in advance for the lengthy explanation but it’s great information to know
Basically, if our ViewModel wouldn’t do anything that works with any specific scheduler (meaning time-based operations: timer, interval, retry, etc.) - you usually won’t even need to inject a scheduler, but in the Metronome’s case you’ll notice we’re injecting the scheduler since we’re using Observable.interval to calculate our “beats”.
OK, great, so far so good.
Now, what happens if instead of Observable.interval(_:scheduler:)
, you would use Driver.interval(_:)
?
Drivers don’t accept a Scheduler, since they always execute on MainScheduler.instance
.
So, actually that’s not entirely true. Driver
is a SharingStrategy
, and you’ll see it’s getting its scheduler from something called SharingScheduler.make()
.
So, what is this SharingScheduler.make()
? By default, it just returns MainScheduler.instance
, which is why all Driver
schedule events on that scheduler by default. So, since we can’t inject it, how can we “mock” that SharingScheduler’s scheduler?
That’s exactly what SharingScheduler.mock
is for!
When you use SharingScheduler.mock(scheduler: testScheduler) { ... commands ... }
- what you’re saying is, whenever you would use a Sharing Strategy, instead of using the default scheduler, use my injected scheduler. So in a way, it’s the same as injecting your scheduler into your View Model, but across all SharingStrategies (Driver/Signal) in the scope of that call.
Sorry if that was a bit technical, hope it helps / made sense to you!
Shai.
That makes sense. And why is it that you don’t need to use SharingScheduler.mock
in your tests in Raytronome? You are using drivers as the output for your ViewModel as right?
Is that because although you are using drivers, the events originate from the testScheduler?
It is the same reason that you don’t necessarily need to inject a scheduler in non-SharingStrategy cases. For many “Immediately Scheduled” thiings in your view model, tests would “just work” usually.
As soon as you use time-based operators (or those that take a scheduler) like delay, retry, throttle, debounce, etc — you’ll want to mock the scheduler. In general it would be a best bet to just always mock the scheduler and be done with it.