Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing Rx Java interval

I have a repeated observable inside a ViewModel as below:

class MainViewModel @Inject constructor(private val ratesUseCase: RatesUseCase) : ViewModel() {

    private var disposable: Disposable? = null
    private val resultLiveData = MutableLiveData<Resource<Map<String, Double>>>()

    fun result() = resultLiveData
    fun getRates(base: String) {
        disposable = Observable
            .interval(1, TimeUnit.SECONDS)
            .flatMap { ratesUseCase.execute(base) }
            .doOnSubscribe { publishResult(Resource.loading(mapOf())) }
            .subscribe(
                {
                    publishResult(Resource.success(values))
                },
                {
                    publishResult(Resource.error(it.localizedMessage, mapOf()))
                }
            )
    }

}

I want to test getRates function. It always return LOADING status What is missing here?

Test case :

@Test
    fun executeSuccess() {
        val base = "CANARY"
        whenever(currencyRepository.getRates(base))
            .thenReturn(Observable.just(map))

        viewModel.result().observeForever(observer)
        viewModel.getRates(base)
        verify(observer).onChanged(Resource.success(map))
    }
like image 454
Metwalli Avatar asked Dec 08 '22 13:12

Metwalli


1 Answers

Thats what happens if you don't pass Scheduler to Observable.interval.

@CheckReturnValue
@SchedulerSupport(SchedulerSupport.COMPUTATION)
public static Observable<Long> interval(long period, TimeUnit unit) {
    return interval(period, period, unit, Schedulers.computation());
}

It will use Schedulers.computation() as default Scheduler.

Your test thread will just finish while interval will not manage to emit anything.

You have to you use TestScheduler to test interval properly. See here: Unit testing Rxjava observables that have a delay

You can override computation scheduler or pass TestScheduler to Observable.interval in your ViewModel. Then you can TestScheduler.advanceTimeBy and control your interval emissions.

like image 114
Tuby Avatar answered Dec 11 '22 08:12

Tuby