Android单元测试需要上下文

时间:2010-01-19 17:54:30

标签: database android unit-testing

我正在编写我的第一个Android数据库后端,我正在努力对我的数据库的创建进行单元测试。

目前我遇到的问题是获取一个有效的Context对象来传递给我的SQLiteOpenHelper实现。有没有办法在扩展TestCase的类中获取Context对象?我想到的解决方案是在我的TestCase的setup方法中实例化一个Activity,然后将该Activity的Context分配给我的测试方法可以访问的字段变量......但似乎应该有一个更简单的方法。

感谢您的投入!

梅西

9 个答案:

答案 0 :(得分:40)

您可以尝试切换到AndroidTestCase。通过查看文档,它似乎应该能够为您提供有效的Context以传递给SQLiteOpenHelper。

编辑: 请记住,您可能必须在Eclipse中的“Android测试项目”中设置测试,因为测试将尝试在模拟器(或真实设备)上执行。

答案 1 :(得分:25)

如果您使用AndroidJUnit4运行测试,则可以使用InstrumentationRegistry方法获取上下文:

InstrumentationRegistry.getTargetContext() - 提供目标应用程序的应用程序Context

InstrumentationRegistry.getContext() - 提供此Instrumentation软件包的Context

对于AndroidX,请使用InstrumentationRegistry.getInstrumentation().getTargetContext()InstrumentationRegistry.getInstrumentation().getContext()

答案 2 :(得分:5)

根据我的经验,使用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
}

其他人都做了什么?

答案 3 :(得分:3)

您应该使用ApplicationTestCase或ServiceTestCase。

答案 4 :(得分:3)

您可以从MockContext派生,并在getResources()上返回MockResources,在getContentResolver()上返回有效ContentResolver,等等。痛苦,一些单元测试

另一种方法是运行例如模拟整个Android操作系统的Robolectric。这些将用于系统测试:运行速度要慢得多。

答案 5 :(得分:2)

扩展AndroidTestCase并调用AndroidTestCase:getContext()对我来说很好,可以获取Context并将其与SQLiteDatabase一起使用。

唯一的问题是它创建和/或使用的数据库与生产应用程序使用的数据库相同,因此您可能希望为两者使用不同的文件名

例如。

  public static final String    NOTES_DB      = "notestore.db";
  public  static final String   DEBUG_NOTES_DB = "DEBUG_notestore.db";

答案 6 :(得分:0)

首先在(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;
}}

答案 7 :(得分:0)

您的测试不是单元测试!

需要时

  • 上下文
  • 在存储上读取或写入
  • 访问网络
  • 或更改任何配置以测试您的功能

您不是在编写单元测试。

您需要使用androidTest程序包编写测试

答案 8 :(得分:-1)

替代解决方案是避免使用ApplicationTestCaseAndroidTestCase或依赖Context的任何其他类。关键是没有必要测试SQLiteORM框架,因此您可以使用基本的CRUD方法创建接口:

public interface UsersManager{
  User createUser(String userId);
  User getUser(String userId);
  boolean updateUser(User user);
  boolean deleteUser(User user);
}

实现两个版本:一个用于测试,另一个用于生产运行时。使用HashMap

可以轻松实现测试版本
public class TestUsersManager implements UsersManager{

  private HashMap<String, User> users = new HashMap();

  public User createUser(String userId){
    User result = new User(userId);
    users.put(userId, user);
    return result;
  }
  //... other methods
}

它运行速度很快(IO)没有磁盘SQLite并且没有外部依赖关系。顺便说一下,这也是额外的抽象级别:对于生产代码,您可以轻松地在ORM框架之间切换。