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