You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何对基于Proto DataStore的PreferenceDataSource进行单元测试?

测试Proto DataStore实现的DataSource方案

要真实验证Proto DataStore的更新、删除等操作,不能直接实例化DataStore(它是抽象类),可以通过Robolectric创建基于内存文件的真实实例,配合协程测试工具完成测试,具体步骤如下:

1. 补充必要测试依赖

确保测试依赖中包含以下内容:

testImplementation "androidx.datastore:datastore-core:1.0.0"
testImplementation "org.robolectric:robolectric:4.12.1"
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.3"

2. 完整测试类实现

@RunWith(RobolectricTestRunner::class)
@ExperimentalCoroutinesApi
class PreferenceDataSourceTest {
    @get:Rule
    val instantExecutorRule = InstantTaskExecutorRule()
    private val testDispatcher = UnconfinedTestDispatcher()

    private lateinit var prefDataSource: PreferenceDataSource
    private lateinit var dataStore: DataStore<UserPreferences>

    @Before
    fun setUp() {
        Dispatchers.setMain(testDispatcher)
        // 创建基于内存文件的Proto DataStore实例
        val context = ApplicationProvider.getApplicationContext<Context>()
        dataStore = context.createDataStore(
            fileName = "test_user_prefs.pb",
            serializer = UserPreferencesSerializer // 你的Proto序列化器
        )
        prefDataSource = PreferenceDataSource(userPreferences = dataStore)
    }

    @Test
    fun `update user preference should persist correctly`() = runTest {
        // 执行DataSource中的更新操作(示例为更新昵称)
        prefDataSource.updateNickname("测试昵称")
        
        // 读取DataStore数据验证结果
        val prefs = dataStore.data.first()
        assert(prefs.nickname == "测试昵称")
    }

    @Test
    fun `clear user preference should reset data`() = runTest {
        // 先写入测试数据
        dataStore.updateData { it.toBuilder().setNickname("旧昵称").build() }
        
        // 执行DataSource中的清除操作
        prefDataSource.clear()
        
        // 验证数据已重置
        val prefs = dataStore.data.first()
        assert(prefs.nickname.isEmpty())
    }
}

3. 关键细节说明

  • 内存DataStore:通过Robolectric的ApplicationProvider获取测试上下文,创建的DataStore使用内存文件系统,不会读写真实磁盘,测试结束后自动清理数据。
  • 协程处理:使用runTest(来自kotlinx-coroutines-test)包裹挂起函数调用,确保测试能等待协程执行完成。
  • Proto序列化器:需要自行实现Serializer<UserPreferences>来完成Proto对象的序列化/反序列化,示例代码如下:
    object UserPreferencesSerializer : Serializer<UserPreferences> {
        override val defaultValue: UserPreferences = UserPreferences.getDefaultInstance()
    
        override suspend fun readFrom(input: InputStream): UserPreferences {
            return try {
                UserPreferences.parseFrom(input)
            } catch (exception: InvalidProtocolBufferException) {
                throw CorruptionException("Cannot read proto.", exception)
            }
        }
    
        override suspend fun writeTo(t: UserPreferences, output: OutputStream) {
            t.writeTo(output)
        }
    }
    

4. 注意事项

  • 确保UserPreferences的Proto定义包含你要测试的字段(比如示例中的nickname)。
  • 所有涉及DataStore的操作都是挂起函数,必须在协程或runTest块中执行。

内容的提问来源于stack exchange,提问作者c-an

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 13:45:30