I want to be able to unit test an Observable
that has a delayed emission, but without actually waiting for the delay time. Is there a way to do this?
I'm currently using a CountDownHatch to delay the assert, and that works fine, but increases the test run time.
Example:
val myObservable: PublishSubject<Boolean> = PublishSubject.create<Boolean>()
fun myObservable(): Observable<Boolean> = myObservable.delay(3, TimeUnit.SECONDS)
@Test
fun testMyObservable() {
val testObservable = myObservable().test()
myObservable.onNext(true)
// val lock = CountDownLatch(1)
// lock.await(3100, TimeUnit.MILLISECONDS)
testObservable.assertValue(true)
}
I was able to come up with a complete solution thanks to @aaron-he's answer.
It uses a combination of TestScheduler
to advance the time and also RxJavaPlugins
to override the default scheduler with the testScheduler. This allowed testing the myObservable()
function without modification or needing to pass in a Scheduler
.
@Before
fun setUp() = RxJavaPlugins.reset()
@After
fun tearDown() = RxJavaPlugins.reset()
@Test
fun testMyObservable() {
val testScheduler = TestScheduler()
RxJavaPlugins.setComputationSchedulerHandler { testScheduler }
val testObservable = myObservable().test()
myObservable.onNext(true)
testScheduler.advanceTimeBy(2, TimeUnit.SECONDS)
testObservable.assertEmpty()
testScheduler.advanceTimeBy(2, TimeUnit.SECONDS)
testObservable.assertValue(true)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With