Android Kotlin单元测试报错:LiveData value was never set问题排查
解决LiveData value was never set.的测试报错
看起来你遇到的问题核心是挂起函数的mock方式不正确,导致协程没有正确执行到设置LiveData值的步骤。让我一步步帮你排查和解决:
问题根源
你的GetStudentsUseCase.execute()应该是一个挂起函数(毕竟你在viewModelScope.launch这个协程作用域里调用它),但你用了普通Mockito的thenReturn来mock挂起函数——这会导致协程的挂起/恢复流程异常,最终_studentLD.value = it这行代码根本没机会执行,自然触发了超时异常。
解决方案
方案1:使用mockito-kotlin的协程扩展(推荐)
这是最简洁的方式,先确保你的测试依赖里引入了mockito-kotlin(版本要和你的Mockito匹配),然后修改测试中的mock逻辑:
@Test fun getStudentsSuccess() = runTest { // 替换原来的thenReturn为coEvery+returns coEvery { getStudentsUseCase.execute() } returns Result.success(studentList) viewModel.getStudents() val value = viewModel.studentLD.getOrAwaitValueTest() assertEquals(value, studentList) }
方案2:用标准Mockito处理挂起函数
如果不想引入额外依赖,你可以用thenAnswer配合suspendCoroutine手动恢复挂起函数的执行:
@Test fun getStudentsSuccess() = runTest { Mockito.`when`(getStudentsUseCase.execute()).thenAnswer { suspendCoroutine { continuation -> continuation.resume(Result.success(studentList)) } } viewModel.getStudents() val value = viewModel.studentLD.getOrAwaitValueTest() assertEquals(value, studentList) }
额外检查:确保MainCoroutineRule正确实现
你的测试用到了MainCoroutineRule,要确认它正确替换了主线程Dispatcher,否则协程可能还是无法在测试环境正常执行。一个标准的实现应该是这样的:
@OptIn(ExperimentalCoroutinesApi::class) class MainCoroutineRule( private val testDispatcher: TestDispatcher = UnconfinedTestDispatcher() ) : TestWatcher() { override fun starting(description: Description) { super.starting(description) Dispatchers.setMain(testDispatcher) } override fun finished(description: Description) { super.finished(description) Dispatchers.resetMain() } }
为什么这样能解决问题?
挂起函数的mock不能用普通的thenReturn,因为它需要遵循协程的挂起协议——要么用支持协程的Mockito扩展来处理,要么手动通过suspendCoroutine来恢复执行,这样协程才能正常走完流程,最终触发LiveData的值更新。
内容的提问来源于stack exchange,提问作者Jonathan
相关产品推荐
相关产品推荐

