3

免责声明 - 我使用 GreenDAO ORM 从我的 android 应用程序中创建和管理 sqlite db。

对于我的 android 应用程序,在编写单元测试时,我希望告诉应用程序切换到使用与正常数据库不同的某个数据库,以确保测试不会污染真实的数据库。相应地,我使用了适当的函数来创建新的数据库并像这样切换到它

public class DbTests extends ApplicationTestCase<MyApp> {
private static final String TAG = "DbTests";
private MyApp mApplication;
private Context mContext;

public DbTests() {
    super(MyApp.class);
}

@Override
protected void setUp() throws Exception {
    Log.d(TAG, "in setUp");
    super.setUp();
    createApplication();
    mApplication = getApplication();
    Log.d(TAG, "setUp done");
}

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


private void setUpFreshInstallNoDataCase(boolean val) {
    assertNotNull(mApplication);
    LocalDataHelpers.setupLocalData(mApplication, InitialConditions.FreshInstallNoData);
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

public void testFreshInstallNoDataCase() {
    Log.d(TAG, "testFreshInstallNoDataCase");
    setUpFreshInstallNoDataCase(true);

    mContext = mApplication.getApplicationContext();
    assertEquals(0, PersonRepository.getAllPersons(mContext).size());
}
}



public class LocalDataHelpers {
public static final String TAG = "LocalDataHelpers";

static MyApp globalApplication;

public static void setupLocalData(MyApp app, String condition) {
    globalApplication = app;
    if(globalApplication.daoSession != null){
        Log.d(TAG, "daoSession not null");
        globalApplication.daoSession.clear();
        globalApplication.setupDatabase(condition);     
    }
}
}

在我的应用程序 onCreate 和 setupDatabase 是这样的

public void onCreate() {
    Log.d(TAG, "onCreate");
    super.onCreate();
    EventBus.getDefault().register(this);
    EventBus.getDefault().post(new PersonEvents.FetchPersonsFromServer());
    setupDatabase(InitialConditions.DefaultSetUp);
}

private void setupDatabase(String condition) {
    DaoMaster.DevOpenHelper helper = null;
    SQLiteDatabase db = null;
    DaoMaster daoMaster = null;
    if (condition.equals(InitialConditions.DefaultSetUp)) {
        helper = new DaoMaster.DevOpenHelper(this, "example-db", null);
        db = helper.getWritableDatabase();
        daoMaster = new DaoMaster(db);
    }
    else if (condition.equals(InitialConditions.FreshInstallNoData)) {
        helper = new DaoMaster.DevOpenHelper(this, "freshInstallNoData-db", null);
        db = helper.getWritableDatabase();
        daoMaster = new DaoMaster(db);
        //clear all possible data here by dropping all tables and recreate
        Log.d(TAG, "Dropping all tables and recreating them");
        DaoMaster.dropAllTables(db, true);
        DaoMaster.createAllTables(db, false);
    }
    if (helper != null && db != null && daoMaster != null) {
        daoSession.clear();
        daoSession = daoMaster.newSession();
    }
    else {
        Log.e(TAG, "setupDatabase Error : condition " + condition + ", either helper or db or daomaster is null");
    }
    List<Pair<String, String>> dbs = getDaoSession().getDatabase().getAttachedDbs();
    for (Pair<String, String> pair : dbs) {
        Log.d(TAG, "setupDatabase <" + pair.first + ", " + pair.second + ">");
    }
}

FetchPersonsFromServer 的 onEvent 获取人员列表并使用 PersonDao 将他们保存到数据库。

现在,如果我从我的设备中清除所有应用程序数据并直接运行测试,则测试通过了。但是,如果我正常运行应用程序,然后运行测试,断言语句将失败

assertEquals(0, PersonRepository.getAllPersons(mContext).size());

大小与默认 db 值相同。

我要疯了,试图找出原因。setupDatabase 中的日志语句显示正确的数据库名称正在显示,即freshdbinstall-db ...

android中不允许使用两个数据库吗?逻辑上应该没有问题吧?是GreenDao不允许吗?我是不是犯了一些基本错误...

请帮忙。


编辑:使用greenDao android ORM库创建超过1个* .db文件甚至模糊相关吗?

更新 1

我使用 adb shell、run-as cat /sdcard/debug/db 和 adb pull 在测试失败后查看默认数据库和新数据库

新数据库与预期的一样,没有 Person 条目,默认有 10 个条目。所以我想问题出在断言/查询调用上...似乎出于某种原因使用了默认数据库...查看存储库代码

public static List<Person> getAllPersons(Context context) {
    return getPersonDao(context).loadAll();
}

private static PersonDao getPersonDao(Context c) {
    return ((MyApp) c.getApplicationContext()).getDaoSession().getPersonDao();
}

根据这似乎会话没有被更新,前一个仍在使用

4

1 回答 1

0

如果您可以选择Robolectric,这就是我们使用内存 SQLite 数据库和填充测试数据的方式:

测试应用程序.java

public class TestApplication extends YourApplication
    implements TestLifecycleApplication {

    @Override
    public void onCreate() {
        super.onCreate();
        YourProvider provider = new YourProvider(YOUR_CONTENT_AUTHORITY);
        provider.onCreate();
        ShadowContentResolver.registerProvider(YOUR_CONTENT_AUTHORITY, provider);
    }
    ...
}

SomeTest.java

@RunWith(RobolectricTestRunner.class)
public class SomeTest {
    @Test
    public void testSQLite() {
        // insert test data into in-memory SQLite
        ShadowContentResolver resolver = shadowOf(Robolectric.getShadowApplication().getContentResolver());
        ContentValues cv = new ContentValues();
        cv.put("column_name", "column_value");
        resolver.insert(YOUR_CONTENT_URI, cv);
        // test against in-memory SQLite
        ...
    }
    ...
}

抱歉,我忘记了我读到这篇文章的文章的来源。

于 2015-02-26T09:06:10.550 回答