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

查看:413
本文介绍了在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.

我读到 ProviderTestCase2 RenamingDelegatingContext 可以用于单独测试数据库。不幸的是,我找不到任何不错的教程/示例,显示如何使用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?!

Cheeerrrrsss!
Giorgio

Cheeerrrrsss!! Giorgio

推荐答案

ProviderTestCase RenamedDelegatingContext 会在数据库上下文中打开之前破坏数据库,所以在这个意义上,它们都有相同的底层方法来打开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.

我建议你去编写内容提供者,而不是创建数据库适配器。您可以使用通用接口来访问数据,无论是存储在DB还是存储在网络上的某处,内容提供商的设计都可以适应以访问这些数据,但需要花费大量的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< ContentProvider> 完全引导您的内容提供者的测试上下文,而无需编写单行代码。

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();
        }

}

例如:

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);
}

}

上下文实现 RenamedDelegatingContext ,一旦 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天全站免登陆