rx-java2 - 如果我使用 Junit5 和 Rxjava,ViewModel Junit 测试会失败。android.os.Looper 中的方法 getMainLooper 未模拟
问题描述
我正在尝试为我的视图模型编写测试用例,并且我正在使用 junit5 和 mockito。问题是我的测试用例总是失败它给了我这个错误
at android.os.Looper.getMainLooper(Looper.java)
at io.reactivex.android.schedulers.AndroidSchedulers$MainHolder.<clinit>
现在我对这个问题做了很多研究,发现这是由于 Rxjava 调度程序,因为它无法在后台线程上运行我按照这个链接并做了所需的步骤,所以之后我的视图模型看起来像这样
MainViewModelTest.kt
@ExtendWith(value = [InstantExecutorExtension::class,TestSchedulerExtension::class])
class MainViewModelTest {
@Mock
private lateinit var repository: GithubRepository
private lateinit var viewModel: MainViewModel
@Before
fun init() {
MockitoAnnotations.initMocks(this)
viewModel = MainViewModel(repository)
}
@Test
fun testNull(){
assertThat(viewModel.observeTrendingRepository(), notNullValue())
verify(repository, never()).makeRequestForTrendingRepo(anyBoolean())
}
@Test
fun fetchTrendingGitHubRepository_emptyDbFirstTimeCase(){
`when`(repository.makeRequestForTrendingRepo(anyBoolean()))
.thenReturn(Flowable.just(Resource.Loading(listOf())))
viewModel.fetchTrendingGitHubRepository(false) // this is where it fails
assertEquals(Resource.Loading<List<Repository>>(listOf()),LiveDataTestUtil.getValue(viewModel.observeTrendingRepository()));
}
}
这是分别处理实时数据和 Rxjava 的 InstantExecutorExtension 和 TestSchedulerExtension。
package com.rajat.zomatotest.utils
import androidx.arch.core.executor.ArchTaskExecutor
import androidx.arch.core.executor.TaskExecutor
import org.junit.jupiter.api.extension.AfterEachCallback
import org.junit.jupiter.api.extension.BeforeEachCallback
import org.junit.jupiter.api.extension.ExtensionContext
class InstantExecutorExtension : BeforeEachCallback, AfterEachCallback {
override fun beforeEach(context: ExtensionContext?) {
ArchTaskExecutor.getInstance().setDelegate(object : TaskExecutor() {
override fun executeOnDiskIO(runnable: Runnable) {
runnable.run()
}
override fun postToMainThread(runnable: Runnable) {
runnable.run()
}
override fun isMainThread(): Boolean {
return true
}
})
}
override fun afterEach(context: ExtensionContext?) {
ArchTaskExecutor.getInstance().setDelegate(null)
}
}
package com.rajat.zomatotest.utils
import io.reactivex.android.plugins.RxAndroidPlugins
import io.reactivex.plugins.RxJavaPlugins
import io.reactivex.schedulers.Schedulers
import org.junit.jupiter.api.extension.AfterTestExecutionCallback
import org.junit.jupiter.api.extension.BeforeTestExecutionCallback
import org.junit.jupiter.api.extension.ExtensionContext
class TestSchedulerExtension : BeforeTestExecutionCallback, AfterTestExecutionCallback {
override fun beforeTestExecution(context: ExtensionContext?) {
RxJavaPlugins.setIoSchedulerHandler { Schedulers.trampoline() }
RxJavaPlugins.setComputationSchedulerHandler { Schedulers.trampoline() }
RxJavaPlugins.setNewThreadSchedulerHandler { Schedulers.trampoline() }
RxAndroidPlugins.setMainThreadSchedulerHandler { Schedulers.trampoline() }
}
override fun afterTestExecution(context: ExtensionContext?) {
RxJavaPlugins.reset()
RxAndroidPlugins.reset()
}
}
我不明白为什么它会给我错误,我已经正确添加了TestSchedulerExtension.kt所以这应该可以工作!!
解决方案
我遇到了同样的问题,我发现解决这个问题的方法是使用
RxAndroidPlugins.setInitMainThreadSchedulerHandler { scheduler }
代替
RxAndroidPlugins.setMainThreadSchedulerHandler { scheduler }
在此链接中,您将找到更多信息。
推荐阅读
- swift - Swift 动画圆形进度条
- r - 获取给定输入值的数据框范围(即 1 返回 df[1:10,])
- java - 使用 Marker 对象之外的数据为 Marker 创建自定义 InfoWindow
- reactjs - React 路由器 v4 动态参数
- reactjs - 如何使用酶和摩卡在 MemoryRouter 中安装组件测试错误状态
- python - 如何根据索引在多维数组中查找值
- android - Android Studio 无法初始化 ADB
- keycloak - 使用 keycloak admin api 获取操作令牌(重置密码)
- angular - 刷新组件后突出显示选定的列表项
- python - 在 y 和 z 中返回 x 是什么意思?