Android 测试rxjava间隔

Android 测试rxjava间隔,android,unit-testing,rx-java2,rx-android,Android,Unit Testing,Rx Java2,Rx Android,我在ViewModel中有一个重复的可观察到的,如下所示: class MainViewModel @Inject constructor(private val ratesUseCase: RatesUseCase) : ViewModel() { private var disposable: Disposable? = null private val resultLiveData = MutableLiveData<Resource<Map<Strin

我在ViewModel中有一个重复的可观察到的,如下所示:

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

}

如果不将
调度程序
传递给
可观察的.interval
,就会发生这种情况

@CheckReturnValue
@SchedulerSupport(SchedulerSupport.COMPUTATION)
public static Observable<Long> interval(long period, TimeUnit unit) {
    return interval(period, period, unit, Schedulers.computation());
}
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.COMPUTATION)
公共静态可观测间隔(长周期,时间单位){
返回间隔(周期、周期、单位、Schedulers.computation());
}
它将使用
调度程序.computation()
作为默认调度程序

测试线程将刚刚完成,而
interval
将无法发出任何消息

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

您可以在ViewModel中覆盖计算调度程序或将
TestScheduler
传递到
Observable.interval

然后您可以
TestScheduler.advanceTimeBy
并控制您的间隔发射。

我确实修复了这里的测试,我就是这样做的。 这里可以观察到两种情况:

1-可通过
1
秒的
interval()
观察到

2-可观察到的
速率secase.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

        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()))
            }
        )
1-为
ratesecase.execute(base)

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

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

    ratesUseCase = RatesUseCase(appSchedulers, currencyRepository)
    viewModel = MainViewModel(ratesUseCase)
}
3-使用
testScheduler.advanceTimeTo
测试
间隔。请不要忘记,这里的订单很重要,如下所示:

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

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

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

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