Android 如何测试使用ContentProvider而不影响生产数据库的活动?
问题 我想测试两个Android类:Android 如何测试使用ContentProvider而不影响生产数据库的活动?,android,dependency-injection,android-testing,android-contentresolver,abstract-factory,Android,Dependency Injection,Android Testing,Android Contentresolver,Abstract Factory,问题 我想测试两个Android类: CommentContentProvider,它扩展并由 CommentActivity,它通过 我目前有两个测试班: CommentContentProviderTest,它扩展了ProviderTestCase2,并使用。这个很好用 CommentActivityTest,它扩展了ActivityInstrumentationTestCase2。除了访问CommentContentProvider的CommentActivity部分之外,这一切都很
,它扩展并由CommentContentProvider
,它通过CommentActivity
,它扩展了CommentContentProviderTest
,并使用。这个很好用ProviderTestCase2
,它扩展了CommentActivityTest
。除了访问ActivityInstrumentationTestCase2
的CommentContentProvider
部分之外,这一切都很好CommentActivity
CommentActivity
访问CommentContentProvider
时,它通过标准ContentResolver
进行访问:
ContentResolver resolver = getContentResolver();
Cursor cursor = resolver().query(...);
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);
:
}
因此,当运行CommentActivityTest
时,它将启动CommentActivity
,它将访问(读取和写入)生产数据库,如上面两行所示
我的问题是如何使CommentActivity
在生产中使用标准的ContentResolver
,而在测试过程中使用MockContentResolver
相关问题
- 这与我在测试ContentProviders时发现的其他问题不同,因为这些问题可以扩展android.test类,这些类是为测试ContentProviders而设计的,而我需要扩展一个类来测试
活动
- 这是类似的,这也是我张贴,但没有回答。如果有帮助的话,我现在愿意使用第三方框架李>
- 是相关的,并导致下面选项1中的解决方案,但我不知道这是否是我的情况下的最佳解决方案
CommentActivity
的注入ContentResolver
(可能是MockContentResolver
或RenamingDelegatingContext
),那就太好了,但我不能这样做,因为s不是
以下哪个选项是最好的,或者有更好的选项吗
选择1
将调试标志添加到启动“注释”活动的Intent
:
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();
}
:
}
public void static setContentResolver(ContentResolver) {
:
}
我不喜欢这个选项,因为我不喜欢将测试相关的代码放在我的非测试类中
选择2
使用抽象工厂模式传递一个Parcelable
类,该类提供真正的ContentProvider
或MockContentProvider
:
ContentResolver resolver = getContentResolver();
Cursor cursor = resolver().query(...);
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;
}
}
在生产中,我传入(通过一个意图)一个RealContentResolverFactory
的实例,在测试中我传入一个MockContentResolverFactory
的实例。因为两者都没有任何状态,所以它们很容易打包/序列化
我对这种方法的担心是,我不想在存在更简单的方法时过度使用设计模式
选择3
将以下方法添加到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();
}
:
}
public void static setContentResolver(ContentResolver) {
:
}
这比选项1更简洁,因为它将ContentResolver
的创建置于CommentActivity
之外,但与选项1一样,它需要修改测试中的类
选择4
让CommentActivityTest
扩展ActivityUnitTestCase
而不是ActivityInstrumentationTestCase2
。这使我可以通过设置CommentActivity
的上下文。我传递的上下文覆盖通常的getContentResolver()
,以使用MockContentResolver
(我在别处初始化)
这是可行的,不需要修改被测试的类,但会增加复杂性,因为
另一个不便之处是,活动必须在触摸模式下进行测试,并在活动仪表测试用例2中定义,但在活动单元测试用例中未定义
FWIW,我对这一点有点着迷,因为我将在我教的Android开发课上介绍它。选项2对我来说似乎是最好的。我不担心工厂的使用;我更担心的是导致远距离行为改变的意图。但是其他解决方案将非生产代码放在生产代码中,因此您测试的内容与生产中的工作方式不太一样。希望这能有所帮助。我对选项2的工作原理感到困惑。如何在产品与测试中选择实际工厂?@NamshubWriter,感谢阅读。我补充了一个问题:在生产中,我传入(通过一个意图)RealContentResolveFactory的一个实例,在测试中传入MockContentResolveFactory的一个实例。由于两者都没有任何状态,因此它们很容易进行打包/序列化。存在一个小的拼写错误。在选项2中,getContextResolver应该是getContentResolver。在相同的情况下。我喜欢选项3,但不幸的是,将其保留在静态字段中会导致内存泄漏(如as 2.2中所警告的)@EllenSpertus:我刚刚就这个主题发布了一个我自己的问题:谢谢你的回答。寂静之声震耳欲聋。:-)