需要上下文的 Android 单元测试
Posted
技术标签:
【中文标题】需要上下文的 Android 单元测试【英文标题】:Android Unit Tests Requiring Context 【发布时间】:2011-01-06 22:20:52 【问题描述】:我正在编写我的第一个 android 数据库后端,我正在努力对我的数据库的创建进行单元测试。
目前我遇到的问题是获取一个有效的 Context 对象以传递给我的 SQLiteOpenHelper 实现。有没有办法在扩展 TestCase 的类中获取 Context 对象?我想到的解决方案是在我的 TestCase 的 setup 方法中实例化一个 Activity,然后将该 Activity 的 Context 分配给我的测试方法可以访问的字段变量......但似乎应该有一个更简单的方法。
【问题讨论】:
【参考方案1】:您可以使用InstrumentationRegistry
方法获取上下文:
InstrumentationRegistry.getTargetContext()
- 提供目标应用的应用Context
。
InstrumentationRegistry.getContext()
- 提供此仪器包的Context
。
对于 AndroidX,请使用 InstrumentationRegistry.getInstrumentation().getTargetContext()
或 InstrumentationRegistry.getInstrumentation().getContext()
。
AndroidX 的新 API: ApplicationProvider.getApplicationContext()
【讨论】:
AndroidJUnit4.class 来自什么依赖? 同上需要一个更完整的例子。 这不是单元测试,而是集成测试。 @birdy 如何将它与 JUnit5 一起使用? 更新:改用ApplicationProvider.getApplicationContext()
【参考方案2】:
您可以尝试切换到AndroidTestCase。从查看文档来看,它似乎应该能够为您提供有效的上下文以传递给 SQLiteOpenHelper。
编辑: 请记住,您可能必须在 Eclipse 的“Android 测试项目”中设置测试,因为测试将尝试在模拟器(或真实设备)上执行。
【讨论】:
扩展AndroidTestCase,然后调用this.getContext()
,返回null
。那是它应该如何工作的吗?我希望返回一个可以与 SQLite 一起使用的丰富上下文
AndroidTestCase 现已弃用,建议改用 InstrumentationRegistry。
android.support.test.InstrumentationRegistry
现在也已折旧。 Google 贬值的速度比您输入 stackoverfow 评论的速度还要快。【参考方案3】:
你的测试不是单元测试!!!
当你需要时
上下文 在存储上读取或写入 接入网络 或更改任何配置以测试您的功能您不是在编写单元测试。
您需要在androidTest
包中编写测试
【讨论】:
你的意思是它不是一个 local 测试(而是一个 instrumented 测试)。androidTest
包中的测试很可能是单元测试。【参考方案4】:
根据我的经验,使用AndroidTestCase:getContext()
方法只会给出一个存根上下文。对于我的测试,我在我的主应用程序中使用了一个空活动并通过它获取Context
。我还用ActivityInstrumentationTestCase2
类扩展了测试套件类。似乎对我有用。
public class DatabaseTest extends ActivityInstrumentationTestCase2<EmptyActivity>
EmptyActivity activity;
Context mContext = null;
...
@Before
public void setUp()
activity = getActivity();
mContext = activity;
... //tests to follow
其他人都做什么?
【讨论】:
【参考方案5】:您可以从MockContext 派生并返回例如getResources()
上的MockResources,getContentResolver()
上的有效ContentResolver,等等。这允许一些单元测试 em>。
另一种方法是运行 Robolectric,它模拟整个 Android 操作系统。这些将用于系统测试:运行起来要慢得多。
【讨论】:
【参考方案6】:您应该使用 ApplicationTestCase 或 ServiceTestCase。
【讨论】:
【参考方案7】:扩展 AndroidTestCase 并调用 AndroidTestCase:getContext() 对我来说可以很好地获取 Context 并将其与 SQLiteDatabase 一起使用。
唯一的问题是它创建和/或使用的数据库将与生产应用程序使用的数据库相同,因此您可能希望为两者使用不同的文件名
例如。
public static final String NOTES_DB = "notestore.db";
public static final String DEBUG_NOTES_DB = "DEBUG_notestore.db";
【讨论】:
【参考方案8】:首先在(androidTest)下创建测试类。
现在使用以下代码:
public class YourDBTest extends InstrumentationTestCase
private DBContracts.DatabaseHelper db;
private RenamingDelegatingContext context;
@Override
public void setUp() throws Exception
super.setUp();
context = new RenamingDelegatingContext(getInstrumentation().getTargetContext(), "test_");
db = new DBContracts.DatabaseHelper(context);
@Override
public void tearDown() throws Exception
db.close();
super.tearDown();
@Test
public void test1() throws Exception
// here is your context
context = context;
【讨论】:
“此类在 API 级别 24 中已弃用。请改用 InstrumentationRegistry。应使用 AndroidX 测试库编写新测试。”以上是关于需要上下文的 Android 单元测试的主要内容,如果未能解决你的问题,请参考以下文章
Android studio 怎么使用单元测试(不需要device)