Robolectric测试WorkManager中Room DAO报Illegal connection pointer错误
问题根因
java.lang.IllegalStateException: Illegal connection pointer 1 异常为Robolectric测试环境下的Room数据库连接冲突问题,通常由以下原因触发:
- 多线程场景(WorkManager Worker线程、测试主线程)同时访问不同的Room数据库实例
- 数据库连接被重复关闭,导致指针指向无效内存地址
- WorkManager异步执行时序不可控,Worker未完成数据写入时ViewModel已提前读取字段,最终触发
servicePrice空指针
解决方案
1. 统一使用全局共享的内存数据库实例
测试全程复用同一个Room内存数据库实例,禁止在Worker、ViewModel内部单独构建数据库实例:
private lateinit var db: AppDatabase @Before fun initDatabase() { val context = ApplicationProvider.getApplicationContext<Context>() db = Room.inMemoryDatabaseBuilder(context, AppDatabase::class.java) .allowMainThreadQueries() .build() // 通过依赖注入框架/手动传入的方式将db实例注入到Worker和ViewModel中 } @After fun closeDatabase() { db.close() }
2. 配置WorkManager测试环境同步执行任务
使用WorkManagerTestInitHelper初始化测试专用WorkManager,强制所有Worker同步执行,消除异步时序问题:
@Before fun initWorkManager() { val context = ApplicationProvider.getApplicationContext<Context>() val testConfig = Configuration.Builder() .setExecutor(SynchronousExecutor()) .setMinimumLoggingLevel(Log.DEBUG) .build() WorkManagerTestInitHelper.initializeTestWorkManager(context, testConfig) }
3. 调整Worker的数据库依赖方式
将数据库实例通过Worker构造函数注入,不要在Worker内部调用Room.databaseBuilder创建新实例,避免多实例连接冲突。
4. 确认Worker执行完成后再读取ViewModel字段
触发WorkManager任务后,等待任务执行状态变为SUCCEEDED后再读取ViewModel的servicePrice字段,避免提前读取未写入的数据:
val workRequest = OneTimeWorkRequestBuilder<CustomWorker>().build() val workManager = WorkManager.getInstance(context) workManager.enqueue(workRequest).result.get() // 阻塞等待任务执行完成 // 再触发ViewModel的数据读取逻辑,验证servicePrice字段
内容的提问来源于stack exchange,提问作者Andrew
相关产品推荐
相关产品推荐

