在Robolectric中testingSQLite数据库

我想在我的Android应用程序中使用Robolectrictesting一个简单的SQLite数据库。 我正在放入一些值,但在读取它们时返回了0行。

我正在使用SQLiteOpenHelper类来访问数据库。

// RequestCache extends SQLiteOpenHelper RequestCache cache = new RequestCache(activity); SQLiteDatabase db = cache.getWritableDatabase(); // Write to DB ContentValues values = new ContentValues(); values.put(REQUEST_TIMESTAMP, TEST_TIME); values.put(REQUEST_URL, TEST_URL); db.insertOrThrow(TABLE_NAME, null, values); // Read from DB and compare values Vector<Request> matchingRequests = new Vector<Request>(); db = cache.getReadableDatabase(); Cursor cursor = db.query(TABLE_NAME, SEARCH_URL_RETURN_COLUMNS, SEARCH_URL_WHERE, new String[] {url}, null, null, ORDER_BY, null); int id = 0; while(cursor.moveToNext()) { long timestamp = cursor.getLong(0); Request request = new Request(id++); request.setUrl(url); request.setCreationTimestamp(new Date(timestamp)); matchingRequests.add(request); } // Assert that one row is returned assertThat(matchingRequests.size(), equalTo(1)); // fails, size() returns 0 

robolectric以外的代码debugging时,按预期工作。 我做错了什么,或者是不可能使用RobolectrictestingSQlite数据库?

Solutions Collecting From Web of "在Robolectric中testingSQLite数据库"

注意:这个答案已经过时了。 如果您使用的是Roboletric 2.X,请参阅https://stackoverflow.com/a/24578332/850787

问题是Robolectric的SQLiteDatabase只存储在内存中,所以当你调用getReadableDatabase或getWritableDatabase时,现有的数据库将被新的空数据库覆盖。

我遇到了同样的问题,我发现唯一的解决scheme是我需要分叉Robolectric项目,并添加ShadowSQLiteOpenHelper来保存数据库,如果相同的上下文被给予两次。 然而,我的叉问题是,我不得不禁止'close() – 函数时,因为否则Connection.close()将销毁内存中的数据库。 我已经提出了请求,但它并没有合并到项目呢。

但随时克隆我的版本,它应该解决您的问题(如果我正确地理解了:P)。 它可以在GitHub上find: https : //github.com/waltsu/robolectric

这里是一个如何使用修改的例子:

 Context c = new Activity(); SQLiteOpenHelper helper = new SQLiteOpenHelper(c, "path", null, 1); SQLiteDatabase db = helper.getWritableDatabase(); // With the db write something to the database db.query(...); SQLiteOpenHelper helper2 = new SQLiteOpenHelper(c, "path", null, 1); SQLitedatabase db2 = helper2.getWritableDatabase(); // Now db and db2 is actually the same instance Cursor c = db2.query(...) ; // Fetch the data which was saved before 

当然,你不需要创build新的SQLiteOpenHelper,但这只是一个例子,传递相同的上下文到两个不同的SQLiteOpenHelper会给同一个数据库。

Robolectric 2.3使用SQLite的一个真正的实现,而不是一个阴影和假货的集合。 现在可以编写testing来validation实际的数据库行为。

在接受的答案中链接的代码不适合我; 它可能已经过时了。 或者,也许我的设置是不同的。 我使用的Robolectric 2.4快照,似乎没有包括一个ShadowSQLiteOpenHelper,除非我错过了一些东西。 无论如何,我想出了一个解决scheme。 以下是我所做的:

  1. 我创build了一个名为ShadowSQLiteOpenHelper的类,并复制上面链接的代码的内容( https://github.com/waltsu/robolectric/blob/de2efdca39d26c5f18a3d278957b28a555119237/src/main/java/com/xtremelabs/robolectric/shadows/ShadowSQLiteOpenHelper&#x3002; Java ),并修复了导入。
  2. 遵循http://robolectric.org/custom-shadows/关于使用自定义阴影的说明,我&#x7528;@Config( shadows = { ShadowSQLiteOpenHelper.class } )注释了我的testing类@Config( shadows = { ShadowSQLiteOpenHelper.class } ) 。 无需定制testing运行器。
  3. 在我的testing中,我实例化了我的SQLiteOpenHelper的子类,传入一个new Activity()作为上下文(Robolectric乐于照顾),并按惯例使用它。

现在,我注意到一个实际的数据库文件是在本地创build的:在使用我的SQLiteOpenHelper子类的testing的第一次运行之后,我在后续的testing中不断收到SQLiteException,因为我的表已经存在; 我可以看到一个名为“path”的文件和一个名为“path-journal”的文件位于我的本地存储库中。 这使我感到困惑,因为我在印象中使用内存数据库。

事实certificate,影子类中的违规行是:

 database = SQLiteDatabase.openDatabase( "path", null, 0 ); 

在getReadableDatabase()和getWriteableDatabase()中。 我知道真正的S​​QLiteOpenHelper可以创build一个内存中的数据库,在查看源代码后,我将其replace为:

 database = SQLiteDatabase.create( null ); 

之后,一切似乎都奏效了。 我可以插入行并将其读回。

希望这可以帮助别人。

发生在我身上的一件奇怪的事情,与这个问题并不完全相关,但是可能会帮助更多人,那就是我也在使用jmockit,而且我在同一个class级的一个testing中使用了它。 但由于某种原因,这导致我的自定义影子类不被使用。 我转换到Mockito只是这个类,它工作正常。