在 Android 上测试数据库:ProviderTestCase2 或 RenamingDelegatingContext? [英] Testing database on Android: ProviderTestCase2 or RenamingDelegatingContext?

查看:27
本文介绍了在 Android 上测试数据库:ProviderTestCase2 或 RenamingDelegatingContext?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经使用 SQLiteOpenHelper 从某些类中的 android.database 包(使用模式 DAO)实现了对数据库的访问.

I've implemented access to a database using SQLiteOpenHelper from the android.database package within some classes (with pattern DAO).

我使用 AndroidTestCase 为这些类编写了一些 junit 测试,但这会导致测试使用与应用程序相同的数据库.

I wrote some junit tests for these classes using an AndroidTestCase but this causes the tests to use the same database as the application.

我读到 ProviderTestCase2RenamingDelegatingContext 可用于单独测试数据库.不幸的是,我找不到任何很好的教程/示例来展示如何使用 ProviderTestCase2/RenamingDelegatingContext 测试数据库.

I read that the ProviderTestCase2 or RenamingDelegatingContext can be used to test the database separately. Unluckily I couldn't find any nice tutorial/example that shows how to test a database with ProviderTestCase2/RenamingDelegatingContext.

谁能指点我一下或给我一些提示或分享一些数据库测试代码?!

Can anyone point me somewhere OR give me some tip OR share some code for database testing?!

干杯!!乔治

推荐答案

ProviderTestCaseRenamingDelegatingContext 都将销毁数据库,如果在它的上下文中打开它之前已经存在,所以从这个意义上说,它们都有相同的低级方法来打开 SQLite 数据库.

Both the ProviderTestCase and RenamingDelegatingContext will destroy the database if one already exists before opening it within it's context, so in that sense they both have the same low-level approach towards opening a SQLite database.

您可以通过在 setUp() 中打开夹具中的数据库来利用这一点,这将确保您在每个测试用例之前使用新的数据库.

You leverage this by opening the database in your fixture in setUp(), which will then ensure that your working with a fresh database before each test case.

我建议您编写内容提供程序而不是创建数据库适配器.您可以使用通用接口来访问数据,无论是存储在数据库中还是通过网络的某个地方,内容提供者的设计都可以适应访问此类数据,但需要付出一些 IPC 开销,这是我们大多数人不应该的不必关心.

I would suggest that you go for writing content providers rather than creating database adapters. You can use a common interface for accessing data, be it stored in the DB or somewhere over the network, the design of content providers can be accommodated to access such data at the cost of a bit of IPC overhead involved that most of us shouldn't have to care about.

如果您这样做是为了访问 SQLite 数据库,则该框架将在单独的进程中为您完全管理数据库连接.作为补充,ProviderTestCase2 完全引导您的内容提供者的测试上下文,而您无需编写一行代码.

If you did this for accessing a SQLite database, the framework would completely manage the database connection for you in a separate process. As added beef, the ProviderTestCase2<ContentProvider> completely bootstraps a test context for your content provider without you having to a write a single line of code.

但是,这并不是说自己进行引导不需要付出巨大的努力.所以假设你有一个这样的数据库适配器;我们将只关注 open() 以获得对我们数据库的写访问权限,没什么特别的:

But, that's not said it isn't such a huge effort to do the bootstrapping yourself. So supposing you had a database adapter as such; we'll just focus on open() for getting write access to our database, nothing fancy:

public class MyAdapter {

    private static final String DATABASE_NAME = "my.db";
    private static final String DATABASE_TABLE = "table";
    private static final int DATABASE_VERSION = 1;


    /**
     * Database queries
     */
    private static final String DATABASE_CREATE_STATEMENT = "some awesome create statement";

    private final Context mCtx;
    private SQLiteDatabase mDb;
    private DatabaseHelper mDbHelper;

    private static class DatabaseHelper extends SQLiteOpenHelper {

        public DatabaseHelper(Context context) {
            super(context, DATABASE_NAME, null, DATABASE_VERSION);
        }

        @Override
        public void onCreate(SQLiteDatabase db) {
            db.execSQL(DATABASE_CREATE_STATEMENT);  
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int a, int b) {
            // here to enable this code to compile
        }
    }

    /**
     * Constructor - takes the provided context to allow for the database to be
     * opened/created.
     * 
     * @param context the Context within which to work.
     */
    public MyAdapter(Context context) {
        mCtx = context;
    }

    /**
        * Open the last.fm database. If it cannot be opened, try to create a new
        * instance of the database. If it cannot be created, throw an exception to
        * signal the failure.
        * 
        * @return this (self reference, allowing this to be chained in an
        *         initialization call)
        * @throws SQLException if the database could be neither opened or created
        */
    public MyAdapter open() throws SQLException {
        mDbHelper = new DatabaseHelper(mCtx);
        mDb = mDbHelper.getWritableDatabase();
        return this;
    }

    public void close() {
            mDbHelper.close();
        }

}

然后你可以这样写你的测试:

Then you could write your test as such:

public final class MyAdapterTests extends AndroidTestCase {

    private static final String TEST_FILE_PREFIX = "test_";
private MyAdapter mMyAdapter;

@Override
protected void setUp() throws Exception {
    super.setUp();

    RenamingDelegatingContext context 
        = new RenamingDelegatingContext(getContext(), TEST_FILE_PREFIX);

    mMyAdapter = new MyAdapter(context);
    mMyAdapter.open();
}

@Override
protected void tearDown() throws Exception {
    super.tearDown();

    mMyAdapter.close();
    mMyAdapter = null;
}

public void testPreConditions() {
    assertNotNull(mMyAdapter);
}

}

所以这里发生的是 RenamingDelegatingContext 的上下文实现,一旦 MyAdapter(context).open() 被调用,将始终重新创建数据库.在调用 MyAdapter.DATABASE_CREATE_STATEMENT 之后,您现在编写的每个测试都将与数据库的状态相反.

So what's happening here is that the context implementation of RenamingDelegatingContext, once MyAdapter(context).open() is called, will always recreate the database. Each test you write now will be going against the state of the database after MyAdapter.DATABASE_CREATE_STATEMENT is called.

这篇关于在 Android 上测试数据库:ProviderTestCase2 或 RenamingDelegatingContext?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆