If you make it normally, you will get ExceptionInitializerError in the part of ```AndroidSchedulers.mainThread ()` ``.
This is because the scheduler returned by ```AndroidSchedulers.mainThread ()` `` depends on Android. (If you depend on Android and do nothing, you need to run it with Android Test using an emulator.) This link to the relevant source I will.
You can work around this issue by simply initializing it as a separate Scheduler with the RxAndroidPlugins mechanism before the test is run.
Below is the source of kotlin. Simply use the Plugin mechanism to define a TestRule that just makes the Scheduler to be used independent of Android.
RxImmediateSchedulerRule.kt
class RxImmediateSchedulerRule : TestRule {
    private val immediate = object : Scheduler() {
        override fun scheduleDirect(run: Runnable, delay: Long, unit: TimeUnit): Disposable {
            return super.scheduleDirect(run, 0, unit)
        }
        override fun createWorker(): Worker {
            return ExecutorScheduler.ExecutorWorker { it.run() }
        }
    }
    override fun apply(base: Statement, description: Description): Statement {
        return object : Statement() {
            @Throws(Throwable::class)
            override fun evaluate() {
                RxJavaPlugins.setInitIoSchedulerHandler({ _ -> immediate })
                RxJavaPlugins.setInitComputationSchedulerHandler({ _ -> immediate })
                RxJavaPlugins.setInitNewThreadSchedulerHandler({ _ -> immediate })
                RxJavaPlugins.setInitSingleSchedulerHandler({ _ -> immediate })
                RxAndroidPlugins.setInitMainThreadSchedulerHandler({ _ -> immediate })
                try {
                    base.evaluate()
                } finally {
                    RxJavaPlugins.reset()
                    RxAndroidPlugins.reset()
                }
            }
        }
    }
}
And just do this before testing. By the way, please refer to this article for the reason why you do not use  @ ClassRule.
@RunWith(PowerMockRunner::class)
@PrepareForTest(Auth::class)
class LoginViewModelTest {
    @Rule
    val schedulers: RxImmediateSchedulerRule = RxImmediateSchedulerRule()
//    companion object {
//        @JvmField
//        @ClassRule
//        val schedulers: RxImmediateSchedulerRule = RxImmediateSchedulerRule()
//    }
    @Test
    fun onClickLogin() {
        val mockAuth = PowerMockito.mock(Auth::class.java)
        val target = LoginViewModel(mockAuth)
        target.mail.set("email")
        target.password.set("password")
        val result = Single.just(AuthEntity().apply {
            accessToken = "123456"
            userId = 100
        })
        PowerMockito.`when`(mockAuth.login("email", "password")).thenReturn(result)
        target.onClickLogin().run()
        Mockito.verify(mockAuth).login("email", "password")
    }
}
        Recommended Posts