与Android的ContentProviders单元测试 [英] Android unit testing with ContentProviders

查看:155
本文介绍了与Android的ContentProviders单元测试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在苦苦挣扎,现在Android上的一个单元测试的问题了一段时间。我的应用程序使用一个SQLite数据库来存储车辆的详细信息。我最近增加了ContentProvider的模式来获取数据(数据库用于直接访问)。

I have been struggling with a unit testing problem on Android for a while now. My app uses a Sqlite DB to store details on vehicles. I have recently added the ContentProvider pattern to retrieve the data (the database used to be accessed directly).

该应用程序工作正常,但在运行模式运行日食时,我偶尔测试失败 - 他们通过在调试模式。在我的设置()方法中,我以我的创建数据库的测试版创建一个RenamingDelegatingContext。所有这一切确实是preFIX的考验。我的数据库,以确保真正的数据库的名称没有被测试code感动。然后我通过这一个数据提供者类,以保持作为一个实例变量直到getWriteableDatabase()的第一个呼叫被称为:

The app works fine, but my tests sporadically fail when run in 'run' mode on eclipse - they pass in 'debug' mode. In my setUp() method, I create a RenamingDelegatingContext in order to create a test version of my database. All this does is prefix "test." to the name of my database to ensure the 'real' database is not touched by test code. I then pass this to a 'data provider' class to keep as a instance variable until the first call to getWriteableDatabase() is called:

public class VehicleProviderTest extends InstrumentationTestCase
{

RenamingDelegatingContext renamingDelegatingContext;
@Override
protected void setUp() throws Exception
{
    super.setUp();
    if(null == renamingDelegatingContext)
    {
        renamingDelegatingContext = new RenamingDelegatingContext(getInstrumentation().getTargetContext(), "test.");

    }

    Log.d("UKMPG", "Initialising UKMPGDataProvider with test context: " + renamingDelegatingContext.getClass().toString());
    MPGDataProvider.init(getTestContext(), Constants.DATABASE_NAME);
    deleteTestDatabase();
}
}

我的ContentProvider的onCreate()方法做了类似的工作,它也通过上下文来的数据提供程序类:

My ContentProvider's onCreate() method does a similar job in that it also passes a Context to the data provider class:

    @Override
public boolean onCreate()
{
    Context context = getContext();
    Log.d("UKMPG", "ContentProvider.onCreate called. Context: " + context.getClass().toString());
    MPGDataProvider.init(getContext(), Constants.DATABASE_NAME);
    return true;
}

现在,这个问题;当我运行我的测试(同样,这并不在调试模式发生)的onCreate()在我的ContentProvider就是所谓的之后的我的设置()方法已通过RenamingDelegatingContext对数据提供程序类,导致在它被覆盖。这意味着活数据库将用于测试(作为测试期望一个空的数据库就会失败)。

Now, the problem; when I run my tests (again, this doesn't happen in debug mode), onCreate() in my ContentProvider is called after my setUp() method has passed the RenamingDelegatingContext to the data provider class, resulting in it being overwritten. This means the live database will be used for the tests (they will fail as the tests expect an empty database).

下面是显示了覆盖正在与注释,解释正在发生的事情有些logcat的:

Here is some logcat showing the overwriting taking place with notes explaining what is happening:

称为ContentProvider.onCreate并将语境UKMPGDataProvider:

ContentProvider.onCreate called and passes Context to UKMPGDataProvider:

01-11 19:22:11.404: D/UKMPG(480): ContentProvider.onCreate called. Context: class android.app.Application
01-11 19:22:11.414: D/UKMPG(480): UKMPGDataProvider.init called. Context: class android.app.Application, db name :mpg_tracker.db

测试通过一个RenamingDelegatingContext到UKMPGDataProvider:

Tests pass a RenamingDelegatingContext to UKMPGDataProvider:

01-11 19:22:13.234: D/UKMPG(498): Initialising UKMPGDataProvider with test context: class android.test.RenamingDelegatingContext
01-11 19:22:13.234: D/UKMPG(498): UKMPGDataProvider.init called. Context: class android.test.RenamingDelegatingContext, db name :mpg_tracker.db

ContentProvider.onCreate再次调用(不同的PID),并传递ApplicationContext来UKMPGDataProvider,覆盖RenamingDelegatingContext:

ContentProvider.onCreate called again (different PID) and passes ApplicationContext to UKMPGDataProvider, overwriting the RenamingDelegatingContext:

01-11 19:22:13.254: D/UKMPG(498): ContentProvider.onCreate called. Context: class android.app.ApplicationContext
01-11 19:22:13.254: D/UKMPG(498): UKMPGDataProvider.init called. Context: class android.app.ApplicationContext, db name :mpg_tracker.db

要getWriteableDatabase()第一次调用发生,所以数据库将与错误的上下文中创建:

First call to getWriteableDatabase() has happened, so database is going to be created with wrong Context:

01-11 19:22:13.265: D/UKMPG(498): database null - going to create it

尚未ContentProvider.onCreate另一个呼叫已经发生了!这一次与常规的上下文。损害已经完成但是,因此这并不能真正使任何区别:

Yet another call to ContentProvider.onCreate has happened! This time with a regular Context. The damage is already done however, so this doesn't really make any difference:

01-11 19:22:13.265: D/UKMPG(498): ContentProvider.onCreate called. Context: class android.app.Application

与错误的上下文创建DB:

Creating DB with wrong Context:

01-11 19:22:13.265: D/UKMPG(498): Creating DB instance with Context: class android.app.ApplicationContext

叫对应于最后ContentProvider.onCreate()调用

init()方法

init() method called corresponding to the last ContentProvider.onCreate() call:

01-11 19:22:13.274: D/UKMPG(498): UKMPGDataProvider.init called. Context: class android.app.Application, db name :mpg_tracker.db

getWriteableDatabase()返回一个非测试数据库:

getWriteableDatabase() is returning a non-test database:

01-11 19:22:13.374: D/UKMPG(498): getWritableDatabase. Path of returned db: /data/data/barry.contentproviderexample/databases/mpg_tracker.db

无法删除数据库下一次测试的测试数据库中不存在:

Failed to delete database for next test as the 'test' database does not exist:

01-11 19:22:13.615: D/UKMPG(498): Database deleted:false

有关完整,这里是来自同一试运行logcat的在调试模式下运行时:

For completeness, here is the logcat from the same test run when run in debug mode:

01-11 19:37:09.514: D/UKMPG(598): ContentProvider.onCreate called. Context: class android.app.Application
01-11 19:37:09.514: D/UKMPG(598): UKMPGDataProvider.init called. Context: class android.app.Application, db name :mpg_tracker.db
01-11 19:37:11.313: D/UKMPG(616): ContentProvider.onCreate called. Context: class android.app.Application
01-11 19:37:11.313: D/UKMPG(616): UKMPGDataProvider.init called. Context: class android.app.Application, db name :mpg_tracker.db

在这一点上ContentProder.onCreate已与非测试语境叫了两声,但这种情况发生的的我的设置()方法,因此它不会影响测试:

At this point ContentProder.onCreate has been called twice with a non-test Context, but this happens before my setUp() method, so it doesn't affect the tests:

01-11 19:37:14.173: D/UKMPG(616): Initialising UKMPGDataProvider with test context: class android.test.RenamingDelegatingContext
01-11 19:37:14.173: D/UKMPG(616): UKMPGDataProvider.init called. Context: class android.test.RenamingDelegatingContext, db name :mpg_tracker.db
01-11 19:37:14.213: D/UKMPG(616): database null - going to create it
01-11 19:37:14.213: D/UKMPG(616): Creating DB instance with Context: class android.test.RenamingDelegatingContext
01-11 19:37:14.364: D/UKMPG(616): getWritableDatabase. Path of returned db: /data/data/barry.contentproviderexample/databases/test.mpg_tracker.db
01-11 19:37:14.794: D/UKMPG(616): Database deleted:true

谁能帮我算出这个?我做得不对,或者这是Android上(线程?)的bug?

Can anyone help me figure this out? Am I doing something wrong, or is this a (threading?) bug in Android?

这是对设备和整个的Andr​​oid版本1.6到4.0重复的。

It is repeatable on devices and across Android versions 1.6 to 4.0.

推荐答案

我觉得你应该叫setContext()在你的设置():

I think you should call setContext() in your setUp():

// warning: untested code
protected void setUp() throws Exception
{
    super.setUp();
    setContext(new RenamingDelegatingContext(getTargetContext(), "test.");

    ...
}

在这种情况下,你可能需要改变你的基类 ProviderTestCase2 可能。

In that case you may need to change your base class to ProviderTestCase2 probably.

这篇关于与Android的ContentProviders单元测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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