- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
问题
我有两个要测试的 Android 类:
CommentContentProvider
, 它扩展了 ContentProvider
并得到 SQLiteDatabase 的支持.CommentActivity
, 它扩展了 Activity
并访问 CommentContentProvider
间接通过 ContentResolver
.我目前有两个测试类:
CommentContentProviderTest
, 它扩展了 ProviderTestCase2<CommentContentProvider>
并使用 MockContentResolver
.这很好用。CommentActivityTest
, 它扩展了 ActivityInstrumentationTestCase2<CommentActivity>
.这工作正常,除了 CommentActivity
的部分该访问 CommentContentProvider
.问题是,当CommentActivity
访问 CommentContentProvider
, 它通过标准 ContentResolver
来实现:
ContentResolver resolver = getContentResolver();
Cursor cursor = resolver().query(...);
因此,当CommentActivityTest
运行,它启动 CommentActivity
,它访问(读取和写入)生产数据库,如以上两行所示。
我的问题是如何制作CommentActivity
使用标准 ContentResolver
在生产中但MockContentResolver
在测试期间。
相关问题
Activity
.可能的解决方案
如果我能注入(inject)一个 ContentResolver
就好了(可能是 MockContentResolver
或 RenamingDelegatingContext
)通过 Intent开始 CommentActivity
,但我不能那样做,因为 Context
s 不是 Parcelable
.
以下哪个选项最好,或者有更好的选项吗?
选项 1
将调试标志添加到 Intent
开始 CommentActivity
:
public class CommentActivity extends Activity {
public static final String DEBUG_MODE = "DEBUG MODE";
private ContentResolver mResolver;
@Override
protected void onCreate(Bundle savedInstanceState) {
:
// If the flag is not present, debugMode will be set to false.
boolean debugMode = getIntent().getBooleanExtra(DEBUG_MODE, false);
if (debugMode) {
// Set up MockContentResolver or DelegatingContextResolver...
} else {
mResolver = getContentResolver();
}
:
}
我不喜欢这个选项,因为我不喜欢将与测试相关的代码放在我的非测试类中。
选项 2
使用抽象工厂模式传递一个Parcelable
提供真实 ContentProvider
的类或 MockContentProvider
:
public class CommentActivity extends Activity {
public static final String FACTORY = "CONTENT RESOLVER FACTORY";
private ContentResolver mResolver;
@Override
protected void onCreate(Bundle savedInstanceState) {
:
ContentResolverFactory factory = getIntent().getParcelableExtra(FACTORY);
mResolver = factory.getContentResolver(this);
:
}
我也有:
public abstract class ContentResolverFactory implements Parcelable {
public abstract ContentResolver getContentResolver(Context context);
}
public abstract class RealContentResolverFactory extends ContentResolverFactory
public ContentResolver getContentResolver(Context context) {
return context.getContextResolver();
}
}
public abstract class MockContentResolverFactory extends ContentResolverFactory
public ContentResolver getContentResolver(Context context) {
MockContentResolver resolver = new MockContentResolver();
// Set up MockContentResolver...
return resolver;
}
}
在生产中,我(通过 Intent )传递了一个 RealContentResolverFactory
的实例, 在测试中我传递了一个 MockContentResolverFactory
的实例.由于两者都没有任何状态,因此它们很容易 Parcelable/Serializable。
我对这种方法的担忧是我不想成为 "that guy"当存在更简单的方法时,谁会过度使用设计模式。
选项 3
将以下方法添加到CommentActivity
:
public void static setContentResolver(ContentResolver) {
:
}
这比选项 1 更简洁,因为它将创建 ContentResolver
在CommentActivity
之外, 但是,与选项 1 一样,它需要修改被测类。
选项 4
有CommentActivityTest
扩展ActivityUnitTestCase<CommentActivity>
而不是 ActivityInstrumentationTestCase2<CommentActivity>
.这让我设置 CommentActivity
通过 setActivityContext()
的上下文.我传递的上下文覆盖了通常的 getContentResolver()
使用 MockContentResolver
(我在别处初始化)。
private class MyContext extends RenamingDelegatingContext {
MyContext(Context context) {
super(context, FILE_PREFIX);
}
@Override
public ContentResolver getContentResolver() {
return mResolver;
}
}
这可行,不需要修改被测类,但增加了更多的复杂性,因为 ActivityUnitTestCase<CommentActivity>.startActivity()
cannot be called in the setUp(
) method, per the API .
另一个不方便的地方是activity必须在触摸模式下测试,setActivityInitialTouchMode(boolean)在 ActivityInstrumentationTestCase2<T>
中定义但不是 ActivityUnitTestCase<T>
.
FWIW,我有点着迷于把它做好,因为我将在我教授的 Android 开发类(class)中展示它。
最佳答案
选项 2 对我来说似乎是最好的。我不介意使用工厂;我对导致远距离行为改变的 Intent 更加困扰。但是其他解决方案将非生产代码放在生产代码中,因此您正在测试的内容与生产中的工作方式不太一样。希望对您有所帮助。
关于android - 如何在不影响生产数据库的情况下测试使用 ContentProvider 的 Activity?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22585067/
我正在开发一个应用程序,我希望它同时适用于 Android 和 Blackberry(将来可能适用于 JavaME)。业务逻辑对所有平台都是通用的 - 因此,代码中的相应层也是如此。 但我也有一个数据
谁能告诉我如何创建一个 ContentProvider,它可以查询多个数据库/ContentProvider 以获得 SearchView 提供的搜索建议。 最佳答案 使用 ContentProvid
我想将一个通用的 POJO 放入 ContentValues 并在 ContentProvider 中解码。 我一直在绞尽脑汁:Parcelables、ContentValues 和插入 SQLite
我在 AsyncTask 中有一个 ContentProvider 访问权限,在手机上查找存储在 sqlite 中的一些数据时通常工作正常。 不过,我还有一些其他后台服务可以进行网络检查以及下载和更新
我正在尝试使用自定义 ContentProvider 提供游戏内高分。它将使用服务器连接而不是 SQLite 数据库。 现在,ContentProvider 的query()、update() 和de
Google 就 ContentProvider 中的路径遍历漏洞发出警告 https://support.google.com/faqs/answer/7496913 Implementations
我见过很多使用ContentProvider与sqlite数据库交互的例子。我在某处读到的文档说 ContentProvider 也能够与普通文件交互。但我们要怎么做呢?到目前为止,我找不到与此相关的
如何将搜索中的引号转义到 ContentProvider?像这样查询: String value = "O'Key" ;/ / string contains a quote Cursor peopl
我正在开发一个将数据存储在 SQLite 数据库中的内容提供程序。在开发过程中,我需要更改模式,或者完全删除数据库并重新构建它(在这个开发阶段我不会升级数据库)。 我找到了数据库文件,存储在/data
大家,我在看android源码。但是我找不到对我有值(value)的东西。实际上,我想知道ContentProvider是否像AIDL一样工作。你知道,AIDL可以实现两个独立应用程序之间的通信。 所
我正在尝试为我的应用程序编写一个内容提供程序,以允许访问我的应用程序存储在 SD 卡上的某些文件。文件的名称是其内容 URI 的哈希值,因此例如 content://my.app.files/test
有什么方法可以利用 ContentProvider 检查我的 Android 手机是否已连接到互联网? 谢谢 最佳答案 我想你想要ConnectivityManager .有一个例子 here . 这
是否可以在应用中初始化contentprovider? 因为我需要为每个用户/服务器组合创建一个数据库,并且我在内容提供者的 oncreate 方法中使用登录信息创建数据库! 最佳答案 根据听起来您正
仅当您需要在多个应用程序之间共享数据时才需要内容提供程序。 这是使用它的唯一目的吗?简单地从 WS 获取数据并将其写入 CP,然后在 Activity 中从这里读取怎么样? iosched呢? :这里
当我从ContentProvider 获取Cursor 对象时,那时我可以使用这个游标对象来检索所有数据。我的问题是: 游标是否包含里面的所有数据。这意味着系统已经查询并花费了时间来加载数据。 这只是
我有一些加密存储 (SQLite),想实现我自己的 ContentProvider。前提是: 只有在以下情况下才应授予/可能访问权限工作/启动我的应用程序 - 总而言之其他情况访问必须被拒绝返回给用户
我有一个 ContentProvider 子类来处理我所有的数据库工作,还有一个在后台运行的服务。 我似乎无法将服务绑定(bind)到 ContentProvider。我是否可以从 ContentPr
我有一个在 list 中声明的 ContentProvider,它是什么时候真正创建的?当应用程序启动时但在启动第一个 Activity 之前?当第一次查询/更新/插入完成时?什么时候? 最佳答案
我想实现一个操作多个表的ContentProvider。到目前为止,这是我尝试过的。我编写了一个 Java Interface,表示每个表都应在其 CRUD 类中实现的 CRUD 操作。 public
我制作了自己的 contentprovider,我通过多次插入将大量数据一次性放入其中。 该应用程序将从外部源接收数据,此时我收到大约 30 个项目(因此是插入的 30 倍)。 现在我注意到这需要很多
我是一名优秀的程序员,十分优秀!