带有超时的单元测试 RxJava 不订阅
Unit test RxJava with timeout not subscribe
我有带超时的单元测试函数 RxJava,但它没有订阅单元测试。
viewModel 上的函数
fun loadData() {
loadDataUseCase.loadData(true)
.subscribeOn(Schedulers.io())
.timeout(30L, TimeUnit.SECONDS, schedulers)
.observeOn(AndroidSchedulers.mainThread())
.doOnSubscribe {
onShowLoading.value = true
onShowError.value = false
onShowContent.value = false
}.subscribe(
{
onConnected.value = true
onShowContent.value = true
onShowError.value = false
onShowLoading.value = false
},
{
onShowError.value = true
onShowLoading.value = false
onShowContent.value = false
}
)
.addTo(compositeDisposable)
}
单元测试功能
@Test
fun `Load data is success`() {
// given
whenever(loadDataUseCase.loadData(true)).thenReturn(Observable.just(true))
// when
viewModel.loadData()
// then
viewModel.onShowError().test().assertValue(false).awaitNextValue().assertValue(false)
}
我尝试调试这个函数,但它没有调用订阅
我有点困惑,onShowError() 是什么 return LiveData?
如果我 运行 相同的代码测试甚至没有完成(我只使用 io 调度程序和 postValue),对你来说它可能在订阅发生之前就完成了:
由于您依赖 Schedulers.io()
,因此您可能甚至在测试 LiveData 之前就完成了整个订阅。
另一个选项是您的 LiveData 已经有一个假值:.assertValue(false)
。然后下一个 .doOnSubscribe
设置已经触发 .awaitNextValue()
并且您的整个测试完成,甚至可以调用订阅。
你的测试应该是固定的,而不是依赖于时间。或者,如果这是不可避免的,那么您必须以某种方式同步您的测试,这里是一个例子:
@Timeout(1, unit = TimeUnit.SECONDS)
@Test
fun `Load data is success`() {
// given
whenever(loadDataUseCase.loadData(true)).thenReturn(Observable.just(true)
val testObserver = liveData.test()
testObserver.assertNoValue() // assert in correct state before actions
// when
loadData(liveData, mock)
//then
testObserver.awaitValueHistorySize(2)
.assertValueHistory(false, false)
}
fun <T> TestObserver<T>.awaitValueHistorySize(count: Int, delay: Long = 10): TestObserver<T> {
awaitValue()
while (valueHistory().size < count) {
// we need to recheck and don't block, the value we are trying to wait might already arrived between the while condition and the awaitNextValue in the next line, so we use some delay instead.
awaitNextValue(delay, TimeUnit.MILLISECONDS)
}
return this
}
我有带超时的单元测试函数 RxJava,但它没有订阅单元测试。 viewModel 上的函数
fun loadData() {
loadDataUseCase.loadData(true)
.subscribeOn(Schedulers.io())
.timeout(30L, TimeUnit.SECONDS, schedulers)
.observeOn(AndroidSchedulers.mainThread())
.doOnSubscribe {
onShowLoading.value = true
onShowError.value = false
onShowContent.value = false
}.subscribe(
{
onConnected.value = true
onShowContent.value = true
onShowError.value = false
onShowLoading.value = false
},
{
onShowError.value = true
onShowLoading.value = false
onShowContent.value = false
}
)
.addTo(compositeDisposable)
}
单元测试功能
@Test
fun `Load data is success`() {
// given
whenever(loadDataUseCase.loadData(true)).thenReturn(Observable.just(true))
// when
viewModel.loadData()
// then
viewModel.onShowError().test().assertValue(false).awaitNextValue().assertValue(false)
}
我尝试调试这个函数,但它没有调用订阅
我有点困惑,onShowError() 是什么 return LiveData?
如果我 运行 相同的代码测试甚至没有完成(我只使用 io 调度程序和 postValue),对你来说它可能在订阅发生之前就完成了:
由于您依赖 Schedulers.io()
,因此您可能甚至在测试 LiveData 之前就完成了整个订阅。
另一个选项是您的 LiveData 已经有一个假值:.assertValue(false)
。然后下一个 .doOnSubscribe
设置已经触发 .awaitNextValue()
并且您的整个测试完成,甚至可以调用订阅。
你的测试应该是固定的,而不是依赖于时间。或者,如果这是不可避免的,那么您必须以某种方式同步您的测试,这里是一个例子:
@Timeout(1, unit = TimeUnit.SECONDS)
@Test
fun `Load data is success`() {
// given
whenever(loadDataUseCase.loadData(true)).thenReturn(Observable.just(true)
val testObserver = liveData.test()
testObserver.assertNoValue() // assert in correct state before actions
// when
loadData(liveData, mock)
//then
testObserver.awaitValueHistorySize(2)
.assertValueHistory(false, false)
}
fun <T> TestObserver<T>.awaitValueHistorySize(count: Int, delay: Long = 10): TestObserver<T> {
awaitValue()
while (valueHistory().size < count) {
// we need to recheck and don't block, the value we are trying to wait might already arrived between the while condition and the awaitNextValue in the next line, so we use some delay instead.
awaitNextValue(delay, TimeUnit.MILLISECONDS)
}
return this
}