【问题标题】:ViewModel Junit Test fails in case when i use Junit5 and Rxjava. Method getMainLooper in android.os.Looper not mocked当我使用 Junit5 和 Rxjava 时,ViewModel Junit 测试失败。 android.os.Looper 中的方法 getMainLooper 未模拟
【发布时间】:2022-01-12 16:37:16
【问题描述】:

我正在尝试为我的视图模型编写测试用例,并且我正在使用 junit5 和 mockito。问题是我的测试用例总是失败它给了我这个错误

    at android.os.Looper.getMainLooper(Looper.java)
    at io.reactivex.android.schedulers.AndroidSchedulers$MainHolder.<clinit>

现在我对这个问题进行了大量研究,发现这是由于 Rxjava 调度程序无法在后台线程上运行我遵循this 链接并执行了所需的步骤,所以在那之后我的观点模型是这样的

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 所以这应该可以工作!!

【问题讨论】:

标签: rx-java2 android-testing junit5 android-viewmodel


【解决方案1】:

我遇到了同样的问题,我发现解决这个问题的方法是使用

RxAndroidPlugins.setInitMainThreadSchedulerHandler { scheduler }

而不是

RxAndroidPlugins.setMainThreadSchedulerHandler { scheduler }

在这个link 你会找到更多信息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-01-08
    • 2022-08-15
    • 2019-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-23
    相关资源
    最近更新 更多