JUnit测试Room数据库迁移:Schema文件无法找到问题求助
看起来你已经走对了大部分路,但在Robolectric单元测试中使用MigrationTestHelper时,Schema文件的查找逻辑和instrumented测试(androidTest)略有不同,这里给你几个针对性的修复方案:
1. 确认Room Schema生成的路径与结构正确
首先确保你的Room配置正确生成了Schema文件到指定目录,在build.gradle的defaultConfig中添加(如果还没加的话):
defaultConfig { javaCompileOptions { annotationProcessorOptions { arguments += ["room.schemaLocation": "$projectDir/schemas".toString()] } } }
这会让Room按数据库类的包路径生成Schema文件,比如你的MyDatabase在com.your.app.db包下,Schema文件会被放在schemas/com/your/app/db/19.json(对应版本19)。这个包路径必须和你传入MigrationTestHelper的MyDatabase::class.java.canonicalName完全匹配,否则Helper找不到对应的Schema。
2. 调整Test SourceSet的Assets配置
你的当前配置已经把schemas目录加入test的assets,但可以尝试更明确的配置方式,确保Robolectric能正确识别:
android { sourceSets { test { java.srcDirs += "$projectDir/src/sharedTest/java" // 明确指定schemas目录作为assets的来源,确保子目录结构被保留 assets.srcDir(project.file("schemas")) } androidTest { assets.srcDir(project.file("schemas")) } } // 其他配置保持不变 }
这里用project.file("schemas")替代files("$projectDir/schemas"),本质是一样的,但能避免字符串拼接可能出现的路径问题。关键是要保留schemas目录下的包路径结构,这样MigrationTestHelper才能按包名找到对应版本的Schema。
3. 修改MigrationTestHelper的初始化方式
在Robolectric单元测试中,InstrumentationRegistry.getInstrumentation()可能无法正确获取到包含assets的Context,尝试改用Robolectric提供的RuntimeEnvironment来获取上下文:
@get:Rule val helper: MigrationTestHelper = MigrationTestHelper( // 替换成Robolectric的RuntimeEnvironment RuntimeEnvironment.getInstrumentation(), MyDatabase::class.java.canonicalName, FrameworkSQLiteOpenHelperFactory() )
如果还是不行,可以尝试直接用Application Context来构造Helper(需要Room测试依赖版本支持此构造函数):
@get:Rule val helper = MigrationTestHelper( RuntimeEnvironment.application, MyDatabase::class.java, listOf(), FrameworkSQLiteOpenHelperFactory() )
注意这个构造函数需要传入数据库类本身,而不是canonicalName。
4. 验证Schema文件的可访问性
可以在测试中添加一个小的验证步骤,确认Robolectric能读取到Schema文件:
@Test fun testSchemaExists() { val schemaPath = "${MyDatabase::class.java.canonicalName.replace('.', '/')}/19.json" val inputStream = RuntimeEnvironment.application.assets.open(schemaPath) assertNotNull("Schema file should exist at path: $schemaPath", inputStream) inputStream.close() }
如果这个测试失败,说明你的assets配置有问题,或者Schema文件的路径不符合预期。
5. 清理并重新构建项目
有时候gradle的缓存会导致资源没有正确同步,执行以下命令清理缓存并重新构建:
./gradlew clean assembleDebug assembleDebugTest
这些步骤应该能帮你解决Schema文件找不到的问题,核心是确保Schema文件的路径与数据库类的包名匹配,且Robolectric的测试环境能正确访问到这些assets文件。
内容的提问来源于stack exchange,提问作者JPM

