测试 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
我在 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