Android Room中SQLiteException抛出时message为null的问题排查
核心原因
1. 测试环境与Android运行时的差异
你在本地JVM单元测试中抛出android.database.sqlite.SQLiteException,但该类是Android SDK专属类,在本地JVM环境下(非设备/模拟器的Instrumented测试),其构造函数无法正确初始化message属性——因为本地JVM没有完整的Android运行时支持,导致调用e.message返回null。
2. 异常类导入包不匹配(潜在可能)
如果测试代码中导入的是java.sql.SQLiteException(Java标准库异常),而业务代码捕获的是android.database.sqlite.SQLiteException(Android SDK异常),两者是完全独立的类。此时业务代码的SQLiteException捕获块不会触发,异常会落到最外层Exception块,但你提到捕获到了SQLiteException,所以这个可能性较低,但仍需检查导入包是否一致。
解决方案
方案1:改用Instrumented测试
将测试代码移至androidTest目录,在Android设备或模拟器上运行测试。此时会使用真实的Android运行时,SQLiteException的message会正常初始化,你能获取到预期的异常信息。
方案2:使用Robolectric模拟Android环境
在本地JVM测试中引入Robolectric框架,它能模拟Android运行时环境,让android.database.sqlite.SQLiteException等类正常工作。配置后,构造异常时传入的message会被正确设置。
方案3:调整测试与业务代码的异常处理逻辑
如果不需要严格模拟SQLiteException,可以改用通用的RuntimeException模拟异常,同时调整业务代码的捕获逻辑;或者在测试中直接构造包含message的异常时,明确指定Android SDK的异常类:
// 测试代码中明确指定包名,避免导入错误 coEvery { projectDao.insertCounter(any()) } throws android.database.sqlite.SQLiteException("Test exception thrown.")
额外提示
你的测试代码中预期的description是空字符串,但实际应该是"Test exception thrown.",需要修正预期值:
val expected = RepositoryException(ErrorResponse("db_error", "Test exception thrown."))
内容的提问来源于stack exchange,提问作者JamieRhys

