问题描述
我已经实现了一个使用 Room 数据库来存储数据的 ContentProvider。实现是在 kotlin 中完成的,它遵循 Google example 中显示的相同模式。 ContentProvider 在应用程序中使用时工作正常。现在我想写一些测试,我依靠 ProviderTestRule 来做这件事。我的配置看起来不错,但不幸的是我收到以下异常,看起来缺少一些初始化,然后上下文不可用。
java.lang.UnsupportedOperationException
at androidx.test.rule.provider.DelegatingContext.getSystemService(DelegatingContext.java:277)
at androidx.room.RoomDatabase$JournalMode.resolve(RoomDatabase.java:517)
at androidx.room.RoomDatabase$Builder.build(RoomDatabase.java:943)
我找不到有关如何测试此方案的任何示例。任何提示都会非常有帮助!
解决方法
ProviderTestRule
在内部使用 DelegatingContext
,它是应用程序上下文的包装器,有意限制其功能。
从源代码中您可以看到 context.getSystemService
被剔除,大部分时间都抛出 UnsupportedOperationException
:
/**
* This method only supports retrieving {@link android.app.AppOpsManager},which is needed by
* {@link android.content.ContentProvider#attachInfo}.
*/
@Override
public Object getSystemService(@NonNull String name) {
checkArgument(!TextUtils.isEmpty(name),"name cannot be empty or null");
// getSystemService(Context.APP_OPS_SERVICE) is only used in ContentProvider#attachInfo for
// API level >= 19.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT
&& Context.APP_OPS_SERVICE.equals(name)) {
return context.getSystemService(Context.APP_OPS_SERVICE);
}
throw new UnsupportedOperationException();
}
我没有明确解释为什么他们首先禁止 ProviderTestRule
访问系统服务。
不幸的是,Room 似乎需要访问 ActivityManager
才能找到最合适的 JournalMode
。
您可以尝试解决这种情况的方法:
- 强制您房间数据库的
JournalMode
为JournalMode.WRITE_AHEAD_LOGGING
(或JournalMode.TRUNCATE
),或 - 如果它没有解决问题,您必须编写自己的
ProviderTestRule
,使用真实的应用程序上下文并允许访问所需的系统服务。