Data Store单元测试报错:单次测试仅允许调用一次runTest
解决Data Store测试中
Only a single call to runTest can be performed during one test报错 问题原因
kotlinx.coroutines.test的runTest在单个测试周期内仅允许调用一次,你的测试方法和@After清理方法各调用了一次,触发了这个限制。
解决方案
去掉@After方法中的runTest,直接利用已创建的TestScope执行清理操作——TestScope本身已绑定测试调度器,可直接运行挂起任务。
修改后的tearDown方法
@After fun tearDown() { // 在测试作用域内启动协程执行Data Store清理 testScope.launch { testDataStore.edit { it.clear() } } // 等待所有调度的协程任务执行完成 testScope.runCurrent() // 取消测试作用域 testScope.cancel() }
完整修改后的测试代码
@HiltAndroidTest @OptIn(ExperimentalCoroutinesApi::class) @RunWith(AndroidJUnit4::class) class MyPreferencesDataSourceTest { private val testContext: Context = ApplicationProvider.getApplicationContext() private val testDispatcher = UnconfinedTestDispatcher() private val testScope = TestScope(testDispatcher + Job()) @get:Rule(order = 0) var hiltRule = HiltAndroidRule(this) @get:Rule(order = 1) val mainDispatcherRule = MainDispatcherRule() private val testDataStore: DataStore<Preferences> = PreferenceDataStoreFactory.create( scope = testScope, produceFile = { testContext.preferencesDataStoreFile( name = AppConstants.APP_NAME, ) }, ) private lateinit var appPreferenceDataSource: AppPreferenceDataSource @Before fun setUp() { hiltRule.inject() appPreferenceDataSource = AppPreferenceDataSource( dataStore = testDataStore, ) } @After fun tearDown() { testScope.launch { testDataStore.edit { it.clear() } } testScope.runCurrent() testScope.cancel() } @Test fun getCurrencyBase_returnsNull() = testScope.runTest { val result = appPreferenceDataSource.getData().first() Assert.assertNull(result) } }
原理说明
TestScope.runCurrent()会立即执行所有已调度到测试调度器的协程任务,无需额外用runTest包装,既完成了Data Store的清理,又避免了多次调用runTest的冲突。
内容的提问来源于stack exchange,提问作者Abhimanyu
相关产品推荐
相关产品推荐

