Метод getMainLooper в android.os.Looper по-прежнему не подвергается насмешкам, даже после добавления RxImmediateSchedulerRule - PullRequest
0 голосов
/ 23 сентября 2019

TrendingViewModelTest

@RunWith(JUnit4::class)
class TrendingViewModelTest {
    private lateinit var trendingRepository: TrendingRepository
    private lateinit var trendingViewModel: TrendingViewModel

    @get:Rule
    val schedulers = RxImmediateSchedulerRule()

    @Before
    fun setUp() {
        trendingRepository = mock(TrendingRepository::class.java)
        trendingViewModel = TrendingViewModel(trendingRepository)
    }

    @Test
    fun testWithNetwork() {
        trendingViewModel.isConnected = true
        trendingViewModel.fetchTrendingRepos()
        verify(trendingRepository, times(1)).getTrendingRepos()
    }

    //...
}

TrendingViewModel

fun fetchTrendingRepos() {
if (isConnected) {
    loadingProgress.value = true
    compositeDisposable.add(
        trendingRepository.getTrendingRepos().subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe({ response ->
                run {
                    loadingProgress.value = false
            },
                { error ->
                    loadingProgress.value = false
                }
            )
    )
} 

RxImmediateSchedulerRule:

class RxImmediateSchedulerRule : TestRule {
    override fun apply(base: Statement?, description: Description?): Statement {
        return object : Statement() {
            @Throws(Throwable::class)
            override fun evaluate() {
                RxJavaPlugins.setIoSchedulerHandler { Schedulers.trampoline() }
                RxJavaPlugins.setComputationSchedulerHandler { Schedulers.trampoline() }
                RxJavaPlugins.setNewThreadSchedulerHandler { Schedulers.trampoline() }
                RxAndroidPlugins.setInitMainThreadSchedulerHandler { Schedulers.trampoline() }

                try {
                    base?.evaluate()
                } finally {
                    RxJavaPlugins.reset()
                    RxAndroidPlugins.reset()
                }
            }
        }
    }
}

TrendingRepositoryImpl:

class TrendingRepositoryImpl @Inject constructor(
    val apiService: GitHubApi,
    val trendingDao: AppDao
) : TrendingRepository {

    override fun getTrendingRepos(): Single<List<TrendingRepo>> {
        return apiService.getTrendingGits()
    }
}

1013

TrendingRepository:
interface TrendingRepository {
    fun getTrendingRepos(): Single<List<TrendingRepo>>
}

Внутри fetchTrendingRepos() инициируется вызов Rxjava, он также подключается к AndroidSchedulers.mainThread (), что может быть причиной его возникновения.

java.lang.RuntimeException:Метод getMainLooper в android.os.Looper не издевается.в android.os.Looper.getMainLooper (Looper.java) в androidx.arch.core.executor.DefaultTaskExecutor.isMainThread (DefaultTaskExecutor.java:77) в androidx.arch.core.executor.ArchTaskExecutor.isMainThread: Archas) в androidx.lifecycle.LiveData.assertMainThread (LiveData.java:461) в androidx.lifecycle.LiveData.setValue (LiveData.java:304) в androidx.lifecycle.MutableLiveData.setValue (MutableLiveData.java:50) в com.man.trendgitz.mvvm.ui.TrendingViewModel.fetchTrendingRepos (TrendingViewModel.kt: 32) в com.manoj.trendgitz.TrendingViewModelTest.testWithNetwork (TrendingViewModelTest.kt: 52) в sun.reflect.NativeMetl.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62) в sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43) в java.lang.reflect.Methoj.jj.model.FrameworkMethod $ 1.runReflectiveCall (FrameworkMethod.java:50) в org.junit.internal.runners.model.ReflectiveCallable.run (ReflectiveCallable.java:12) в org.junit.runners.model.FrameworkMethod.invokeExplosively (FrameworkMethod.java:47) в org.junit.internal.runnerseMatementsInvokeMethod.java:17) в org.junit.internal.runners.statements.RunBefores.evaluate (RunBefores.java:26) в org.junit.runners.ParentRunner.runLeaf (ParentRunner.java:325) в org.junit..BlockJUnit4ClassRunner.runChild (BlockJUnit4ClassRunner.java:78) в org.junit.runners.BlockJUnit4ClassRunner.runChild (BlockJUnit4ClassRunner.java:57) в org.junit.runner.runners.ParentRunner $ 1.schedule (ParentRunner.java:71) в org.junit.runners.ParentRunner.runChildren (ParentRunner.java:288) в org.junit.runners.ParentRunner.access $ 000 (ParentRunner.java:58)org.junit.runners.ParentRunner $ 2.evaluate (ParentRunner.java:268) в org.junit.runners.ParentRunner.run (ParentRunner.java:363) в org.junit.runner.JUnitCore.run (JUnitCj.: 137) в com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs (JUnit4IdeaTestRunner.java:68) в com.intellij.rt.execution.junit.IdeaTestRunner $ Repeest.startRunnerjtw.исполнительный процесс

1 Ответ

1 голос
/ 23 сентября 2019

При обновлении значения LiveData вы также должны добавить @get:Rule var rule: TestRule = InstantTaskExecutorRule().

Не забудьте добавить следующее в build.gradle файл:

dependencies {
    // ...
    testImplementation "androidx.arch.core:core-testing:2.1.0"
}

Кроме того, измените свой тестовый код соответствующим образом, чтобы избежать: NullPointerException:

@Test
fun testWithNetwork() {
    trendingViewModel.isConnected = true
    Mockito.`when`(trendingRepository.fetchTrendingRepos()).thenReturn(Single.just(listOf<TrendingRepo>()))
    trendingViewModel.fetchTrendingRepos()
    verify(trendingRepository, times(1)).getTrendingRepos()
}

Mockito.when() позволяет вам выполнять различные действия каждый раз, когда вызывается ваш фиктивный метод.Если вы его не используете, вы можете увидеть возможные NullPointerException в зависимости от вашей функции тестирования.

...