【发布时间】:2018-10-15 11:41:40
【问题描述】:
我正在尝试对使用 Kotlin 协程制作的演示者进行单元测试,这也是我第一次使用 Mockito
每当我尝试运行单元测试时,它在协程中第一次尝试对我的视图执行任何操作时都会收到以下错误
Exception in thread "main @coroutine#1 @coroutine#2" java.lang.NullPointerException
at .signin.SignInPresenter$subscribe$1.doResume(SignInPresenter.kt:45)
at kotlin.coroutines.experimental.jvm.internal.CoroutineImpl.resume(CoroutineImpl.kt:54)
at kotlinx.coroutines.experimental.DispatchedKt.resumeCancellable(Dispatched.kt:208)
at kotlinx.coroutines.experimental.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:35)
at kotlinx.coroutines.experimental.CoroutineStart.invoke(CoroutineStart.kt:111)
at kotlinx.coroutines.experimental.AbstractCoroutine.start(AbstractCoroutine.kt:161)
at kotlinx.coroutines.experimental.BuildersKt.launch(Builders.kt:68)
at kotlinx.coroutines.experimental.BuildersKt.launch$default(Builders.kt:61)
at .signin.SignInPresenter.subscribe(SignInPresenter.kt:42)
这是我的presenter的相关部分,错误中引用的行是view.showSigninPanel
class SignInPresenter(
private val view: SignInContract.View,
private val userRepo: ParseAuthController,
private val contextPool: CoroutineContextProvider
) : SignInContract.Presenter {
private val coroutineJobs: MutableList<Job> = mutableListOf()
override fun subscribe() {
view.loadBackgroundImage()
view.setUpSignInPanel()
view.setUpKeyboardListener()
coroutineJobs.add(launch(contextPool.Main) {
if (!userRepo.isAuthenticated()) {
view.showSignInPanel()
subscribeToLoginValidation()
subscribeToPaswordEmailValidation()
} else {
view.launchMainActivity()
}
})
}
对userRepo.isAuthenticated() 的调用是暂停调用
根据这篇文章,我将一个测试协程上下文传递给我的演示者
https://android.jlelse.eu/mastering-coroutines-android-unit-tests-8bc0d082bf15
class TestContextProvider : CoroutineContextProvider() {
override val Main: CoroutineContext = Unconfined
override val IO: CoroutineContext = Unconfined
}
这是我目前的单元测试
class SignInPresenterTest {
private lateinit var view: SignInContract.View
private lateinit var presenter: SignInPresenter
private lateinit var parseAuthController: ParseAuthController
@Before
fun setUp() {
view = mock(SignInContract.View::class.java)
parseAuthController = mock(ParseAuthController::class.java)
presenter = SignInPresenter(
view,
parseAuthController,
TestContextProvider()
)
}
@After
fun tearDown() {
presenter.dispose()
}
@Test
fun subscribeNotAuthenticatedShowSignInPanel() {
runBlocking {
val expectedResult = false
`when`(parseAuthController.isAuthenticated()).thenReturn(expectedResult)
presenter.subscribe()
}
verify(view).showSignInPanel()
}
}
更新:我一直在做一些额外的测试,看起来如果我在演示者if (!userRepo.isAuthenticated()) 中删除暂停调用,它不会崩溃,我可以验证 Mockito 是否运行了某些东西,但这不是不是一个实际的解决方案...但是该挂起呼叫的某些问题导致了问题?
【问题讨论】:
-
你能分享代码吗,我也有同样的问题,lib 已更新但不起作用
-
我无法再访问这个代码库了。也许尝试做一个 ./gradlew build --refresh-dependencies 看看是否能解决它?
标签: android unit-testing kotlin mockito kotlinx.coroutines