需要上下文的 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)

Android单元测试与模拟测试详解

徒手搭建Python单元测试框架

单元测试

[Android]_[中级]_[如何对服务和Activity进行单元测试]

[Android]_[中级]_[如何对服务和Activity进行单元测试]