質問

AndroidアプリケーションでRoboLectricを使用して、単純な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以外でコードをデバッグするとき、これは期待どおりに機能します。私は何か間違ったことをしていますか、それともrobolectricを使用してSQLiteデータベースをテストすることはできませんか?

役に立ちましたか?

解決

注:この答えは時代遅れです。ロボレトリック2.xを使用している場合は、参照してください https://stackoverflow.com/a/24578332/850787

問題は、robolectricのsqlitedatabaseがメモリにのみ保存されているため、getReadableAdaTabaseまたはgetWritabledAtabaseを呼び出すと、既存のデータベースが新しい空のデータベースでオーバーライドされます。

私は同じ問題に走っていましたが、私が見つけた唯一の解決策は、同じコンテキストが2回与えられた場合にデータベースを保存するためにShadowsQLiteOpenHelperを追加する必要があるということでした。ただし、フォークの問題は、CONTEXが指定されている場合、CONTEXが指定されている場合、Close()を「無効」する必要があることです。私はそれをプルリクエストしましたが、それはまだプロジェクトに合併していません。

しかし、私のバージョンを自由にクローンすると、問題を修正する必要があります(正しく理解した場合:p)。 Githubで見つけることができます: 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 

もちろん、新しいsqliteopenhelperを作成する必要はありませんが、それは同じコンテキストを2つの異なるsqliteopenhelperに渡すと同じデータベースが得られるという例にすぎません。

他のヒント

ロボレクトリック 2.3 影と偽物のコレクションの代わりに、SQLiteの実際の実装を使用します。これで、実際のデータベース動作を検証するためにテストを作成できるようになりました。

受け入れられた答えにリンクされているコードは、私にとってはうまくいきませんでした。それは時代遅れかもしれません。または、おそらく私のセットアップはまったく異なります。私はロボレクトリック2.4スナップショットを使用していますが、これには何かを見逃さない限り、ShadowsQliteopenhelperは含まれていないようです。いずれにせよ、私は解決策を見つけました。これが私がしたことです:

  1. ShadowsQLiteOpenHelperというクラスを作成し、上記のコードの内容をコピーしました(https://github.com/waltsu/robolectric/blob/de2efdca39d26c5f18a3d278957b28a555119237/src/main/java/com/xtremelabs/robolectric/shadows/shadowsqlitepenhelperperperper.java)、および輸入を修正しました。
  2. 指示に従ってください http://robolectric.org/custom-shadows/ カスタムシャドウを使用するために、テストクラスに注釈を付けました @Config( shadows = { ShadowSQLiteOpenHelper.class } ). 。カスタムテストランナーは必要ありません。
  3. 私のテストでは、sqliteopenhelperのサブクラスをインスタンスし、 new Activity() コンテキスト(ロボレクトリックが喜んでそれを処理します)として、通常あたりそれを使用しました。

この時点で、実際のデータベースファイルがローカルに作成されていることに気付きました。SQLiteOpenHelperサブクラスを使用したテストの最初の実行の後、テーブルが既に存在していたため、後続のテストでSQLiteExceptionを取得し続けました。また、「Path」というファイルと、地元のリポジトリに座っている「Path-Journal」と呼ばれるファイルが表示されました。シャドウクラスがメモリ内データベースを使用しているという印象を受けていたので、これは私を混乱させました。

Shadow Classの問題は次のとおりです。

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

getReadableAdataBase()とgetWriteAbledataBase()の両方で。実際のsqliteopenhelperがメモリ内データベースを作成できることを知っていました。ソースを見て、それがどのように行われるかを確認した後、上記の行を次のように置き換えました。

database = SQLiteDatabase.create( null );

その後、すべてが機能しているようです。行を挿入して読むことができます。

うまくいけば、これは他の誰かに役立ちます。

この質問に正確に関係していないが、誰かをさらに助けるかもしれない私に起こった奇妙なことの1つは、私もjmockitを使用しており、同じクラスで1つのテストでそれを使用していたことです。しかし、何らかの理由で、これは私のカスタムシャドウクラスを使用しませんでした。私はそのクラスのためにモッキートに切り替えました、そしてそれは正常に動作します。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top