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))
}
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.
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