Android Room数据库单元测试运行报job未完成异常如何解决
错误核心原因
- 你将Room返回的
Flow通过asLiveData()转为LiveData后,未触发LiveData的观察逻辑,对应Flow的收集协程没有启动,且asLiveData()默认使用Dispatchers.IO调度器,和runBlockingTest使用的测试协程调度器不兼容,测试结束时该IO协程任务还未完成,因此抛出This job has not completed yet异常。 - 即使调度问题解决,你直接取
receivedItem.value也会得到null,因为未激活的LiveData不会主动从Flow里拉取数据,断言必然失败。
修复方案
方案1:直接测试Flow(推荐,最简便)
不需要转LiveData,直接获取Flow的第一个发射值即可完成断言,修改测试方法代码如下:
@ExperimentalCoroutinesApi @Test @Throws(Exception::class) fun insertAndGetItem() = runBlockingTest { val boira = Item(0, "Boira", 0.35, 36) val apple = Item(0, "Apple", 0.60, 50) val mango = Item(0, "Mango", 2.10, 43) itemDao.insert(boira) itemDao.insert(apple) itemDao.insert(mango) // 直接获取Flow的第一个值,不需要转LiveData val receivedItem = itemDao.getAllItems().first() assertThat(receivedItem.size, equalTo(3)) }
需要额外导入Flow的first扩展:import kotlinx.coroutines.flow.first
方案2:保留LiveData测试逻辑
如果你确实需要测试转为LiveData后的逻辑,需要做以下修改:
- 添加测试依赖:在build.gradle(模块级)的androidTestImplementation中引入
androidx.arch.core:core-testing:2.2.0(可替换为对应最新版本) - 测试类中添加LiveData同步执行规则,保证LiveData的操作都在当前线程执行:
@get:Rule val instantTaskExecutorRule = InstantTaskExecutorRule()
- 使用LiveData测试的
getOrAwaitValue()扩展方法主动获取值,修改测试方法对应代码:
val receivedItem = itemDao.getAllItems().asLiveData().getOrAwaitValue() assertThat(receivedItem.size, equalTo(3))
内容的提问来源于stack exchange,提问作者Raw Hasan
相关产品推荐
相关产品推荐

