RxJava test `repeat` on observable create endless loop on tests

Luca Nicoletti :

I have set up my ViewModel to repeat an API call endlessly this way:

useCase.fireAPICall(params)
   .subscribeOn(Schedulers.io())
   .observeOn(AndroidSchedulers.mainThread())
   .repeat()
   .delay(1, TimeUnit.SECONDS)
   .subscribe(::onSuccess, ::onFailed)

In my unit tests, I'm trying to mock the API call and check whether or not the LiveData inside the ViewModel (updated in the ::OnSuccess method) is updated accordingly.

Working unit test that tests a failure:

val error = Throwable("")
// Arrange
Mockito.`when`(repo.apiCall(params))
   .thenReturn(Single.error(error))
// Act
viewModel.init()
// Verify
Mockito.verify(postDetailsViewStateObserver)
   .onChanged(Error(error))

** Non-working:** f instead, I try to mock a valid response from that API call with:

// Arrange
Mockito.doReturn(Single.just(Success(result, list)))
   .`when`(repo).apiCall(params)

Then the ViewModel repeat() generates an endless loop which blocks my unit test without completing it ever.

Question: how can we test a repeat() situation by checking just the first thing emitted on that observable?

Denathan :

You need to provide a scheduler for delay to take advantage of the time in test so e.g.:

val testScheduler = TestScheduler()
RxJavaPlugins.setComputationSchedulerHandler { testScheduler }

And after that call testScheduler.advanceTimeBy(1, TimeUnit.SECONDS) so you will move forward by one second. To make it work you should probably also change the order, delay should be before the repeat.

You need to setComputationSchedulerHandler as delay is by default uses this scheduler.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=174989&siteId=1