测试 Rx Java 间隔

Testing Rx Java interval

我在 ViewModel 中有一个重复的 observable,如下所示:

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

}

我想测试 getRates 函数。它总是 return 加载状态 这里缺少什么?

测试用例:

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

如果您不将 Scheduler 传递给 Observable.interval,就会发生这种情况。

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

它将使用 Schedulers.computation() 作为默认调度程序。

您的测试线程将刚刚完成,而 interval 将不会发出任何东西。

您必须使用 TestScheduler 来正确测试间隔。 看这里:

您可以覆盖计算调度程序或在您的 ViewModel 中将 TestScheduler 传递给 Observable.interval。 然后你可以 TestScheduler.advanceTimeBy 并控制你的间隔排放量。

我确实在这里修复了测试,我就是这样做的。 这里有两个可观察的:

1- 可观察到 interval() 1 秒。

2- ratesUseCase.execute(base) 的 Observable。 正如您在下面看到的那样 MainViewModel

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

MainViewModel

中测试getRates

1- 为 ratesUseCase.execute(base)

注入测试调度程序

2- 使用 RxJavaPlugins.setComputationSchedulerHandler 更改默认调度程序,如下所示

@Before
fun setUp() {
    val testScheduler = TestScheduler()
    RxJavaPlugins.setComputationSchedulerHandler { testScheduler }

    ratesUseCase = RatesUseCase(appSchedulers, currencyRepository)
    viewModel = MainViewModel(ratesUseCase)
}

3- 使用testScheduler.advanceTimeTo 测试interval。请注意这里的顺序很重要,如下所示:

3.a:模拟存储库

3.b : 观察 ViewModel LiveData

3.c:提前时间间隔

3.d : 验证结果

    val base = "BASE"
    whenever(currencyRepository.getRates(base))
        .thenReturn(Observable.just(map))

    viewModel.result().observeForever(observer)
    viewModel.getRates(base)

    testScheduler.advanceTimeTo(1, TimeUnit.SECONDS)
    verify(observer).onChanged(
        Resource.success(map)
    )

可以找到完整的项目和测试用例here