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()
    }
}
TrendingRepository:
interface TrendingRepository {
    fun getTrendingRepos(): Single<List<TrendingRepo>>
}
Inside fetchTrendingRepos() an Rxjava call is initiated, it also hooks onto 'AndroidSchedulers.mainThread()' that might be the reason causing it.
java.lang.RuntimeException: Method getMainLooper in android.os.Looper not mocked. at android.os.Looper.getMainLooper(Looper.java) at androidx.arch.core.executor.DefaultTaskExecutor.isMainThread(DefaultTaskExecutor.java:77) at androidx.arch.core.executor.ArchTaskExecutor.isMainThread(ArchTaskExecutor.java:116) at androidx.lifecycle.LiveData.assertMainThread(LiveData.java:461) at androidx.lifecycle.LiveData.setValue(LiveData.java:304) at androidx.lifecycle.MutableLiveData.setValue(MutableLiveData.java:50) at com.manoj.trendgitz.mvvm.ui.TrendingViewModel.fetchTrendingRepos(TrendingViewModel.kt:32) at com.manoj.trendgitz.TrendingViewModelTest.testWithNetwork(TrendingViewModelTest.kt:52) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.junit.runner.JUnitCore.run(JUnitCore.java:137) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68) at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47) at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242) at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
As you update LiveData value, you should add @get:Rule var rule: TestRule = InstantTaskExecutorRule() also.
Don't forget to add following to build.gradle file:
dependencies {
    // ...
    testImplementation "androidx.arch.core:core-testing:2.1.0"
}
Also, change your test code accordingly to avoid 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() lets you to do different actions every time your mock method is called. If you don't use it, you may see possible NullPointerException depending on your test function.
Add the below lines under android {} in your app's build.gradle
testOptions {
            // Used for Unit testing Android dependent elements in /test folder
            unitTests.includeAndroidResources  = true
            unitTests.returnDefaultValues = true
        }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With