【问题标题】:Testing Rx Java interval测试 Rx Java 间隔
【发布时间】:2019-01-14 12:24:28
【问题描述】:

我在 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 函数。它总是返回 LOADING 状态 这里缺少什么?

测试用例:

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

【问题讨论】:

  • 您是否覆盖了运行 Interval 的调度程序?
  • 是的!像这样subscribeOn(Schedulers.trampoline()).observeOn(Schedulers.trampoline())
  • 嗯,默认情况下,interval 在计算线程上运行。您应该能够使用 RxJavaPlugins API 为测试设置新的调度程序。使用 setInitComputationSchedulerHandler 将计算调度程序上运行的所有内容路由到 trampoline() 调度程序。
  • 现在我已经注射了它们。间隔现在在 Schedulers.trampoline() Observable .interval(1,TimeUnit.SECONDS).compose(appSchedulers.observableTransformer()) 上运行,但仍然给出相同的结果
  • 哦,我明白了。您是否尝试调试 onNext 和 onComplete 以查看它们是否真正按顺序运行?这很奇怪。另外,你也在运行 InstantTaskExecutorRule,对吧?

标签: android unit-testing rx-java2 rx-android


【解决方案1】:

如果您不将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 正确测试间隔。 看这里: Unit testing Rxjava observables that have a delay

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

【讨论】:

    【解决方案2】:

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

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

    2- 可观察到 ratesUseCase.execute(base)。 正如您在下面看到的,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找到

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-22
      • 1970-01-01
      相关资源
      最近更新 更多