Bootstrapper
Bootstrapper

Reputation: 1159

How to unit test RxJava retryWhen

I am trying to use an exponential backoff with RxJava Completable and the code works fine when I try it. So was trying to add a unit test to cover it but am not sure how we can test the retryWhen part here.

    fun makeCall(
        scheduler: Scheduler = scheduler.io()
    ) : Completable {
        val value = "myString"

        return myCompletable(value)
            .retryWhen { errors: Flowable<Throwable> ->
                errors
                    .zipWith(Flowable.range(1, 3))
                    .flatMap { errorRetryPair: Pair<Throwable, Int> ->
                        Flowable.timer(2.toDouble().pow(errorRetryPair.second.toDouble()).toLong(), TimeUnit.SECONDS)
                    }
            }.subscribeOn(scheduler)
    }

does anyone know how we can test this? (haven't been able to find much info about testing to make sure the retryWhen works)

TIA

Upvotes: 1

Views: 1541

Answers (1)

Bob Dalgleish
Bob Dalgleish

Reputation: 8227

Unit testing RxJava timed operations is best done with a TestScheduler.

// in your test code
simulateFailure();
long firstStepMs = 2_000; // first backoff time in ms
long epsilon = 40;        // 10ms is too small
scheduler.advanceTimeBy( firstStepMs - epsilon, TimeUnit.MILLISECONDS );
// test to see that resubscription has NOT occurred
scheduler.advanceTimeBy( 2 * epsilon, TimeUnit.MILLISECONDS );
// test to see that first resubscription HAS occurred

and repeat for different back off times. The granularity of advancing the clock is up to you. epsilon must be larger than 10 milliseconds because of how timer scheduling in Java works; you certainly won't be able to usefully measure any shorter intervals.

Upvotes: 1

Related Questions