Question

Je suis en train de tester une base de données SQLite simple à l'aide Robolectric dans mon application Android. Je mets dans certaines valeurs, mais quand les relisant 0 lignes sont renvoyées.

J'utilise la classe SQLiteOpenHelper pour accéder à la base de données.

// 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

Lors du débogage du code en dehors robolectric cela fonctionne comme prévu. Suis-je faire le mal de quoi que ce soit ou est-il pas possible de tester les bases de données SQLite en utilisant Robolectric?

Était-ce utile?

La solution

NOTE: Cette réponse est obsolète. Si vous utilisez Roboletric 2.X, s'il vous plaît voir https://stackoverflow.com/a/24578332/850787

Le problème est stocké uniquement SQLiteDatabase de Robolectric dans mémoire, donc lorsque vous appelez getReadableDatabase ou getWritableDatabase, la base de données existante sera remplacée avec une nouvelle base de données vide.

je courais au même problème et la seule solution que j'ai trouvé était que je devais bifurquer le projet Robolectric et ajouté ShadowSQLiteOpenHelper la base de données enregistrer si même contexte est donné deux fois. Cependant, le problème avec ma fourchette est que je devais « désactiver » close () - fonction lorsque Contex est donnée parce que sinon Connection.close () va détruire la base de données en mémoire. J'ai fait la demande de traction pour elle, mais ce ne sont pas fusionnés au projet encore.

Mais ne hésitez pas à cloner ma version et il devrait résoudre votre problème (Si je compris correctement: P). Il se trouve sur GitHub: https://github.com/waltsu/robolectric

Voici un exemple comment utiliser la modification:

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 

Ofcourse vous n'avez pas besoin de créer de nouvelles SQLiteOpenHelper, mais qui est juste par exemple que le passage même contexte à deux SQLiteOpenHelper différentes donnera même base de données.

Autres conseils

Robolectric 2.3 utilise une véritable mise en œuvre de SQLite au lieu d'une collection d'ombres et de faux. Les tests peuvent maintenant être écrits afin de vérifier le comportement de la base de données réelle.

Le code lié à la réponse acceptée ne fonctionnait pas pour moi; il peut être à jour. Ou peut-être ma configuration est tout simplement différent. J'utilise instantané Robolectric 2.4, ce qui ne semble pas inclure un ShadowSQLiteOpenHelper, à moins que je manqué quelque chose. Dans tous les cas, je me suis dit une solution. Voici ce que je l'ai fait:

  1. J'ai créé une classe appelée ShadowSQLiteOpenHelper et collé copie le contenu du code lié ci-dessus ( https://github.com/waltsu/robolectric/blob/de2efdca39d26c5f18a3d278957b28a555119237/src/main/java/com/xtremelabs/robolectric/shadows/ShadowSQLiteOpenHelper.java ) et fixe les importations.
  2. En suivant les instructions sur http://robolectric.org/custom-shadows/ pour l'utilisation personnalisée ombres, j'annotés ma classe de test avec @Config( shadows = { ShadowSQLiteOpenHelper.class } ). Pas besoin d'un coureur de test personnalisé.
  3. Dans mes tests, j'instancié ma sous-classe de SQLiteOpenHelper, en passant dans un new Activity() que le contexte (Robolectric prend heureusement soin de cela), et utilisé par d'habitude.

Maintenant, à ce stade, j'ai remarqué qu'un fichier de base de données réelle a été obtenir créé localement: après la première manche d'un test qui a utilisé ma sous-classe SQLiteOpenHelper, je continuais obtenir un SQLiteException sur les tests ultérieurs, car ma table existait déjà; et je pouvais voir un fichier appelé « chemin » et un fichier appelé « chemin journal » assis dans mon dépôt local. Cela me confus parce que j'avais l'impression que la classe d'ombre utilisait une base de données en mémoire.

Il se trouve la ligne d'offenser dans la classe d'ombre est:

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

dans les deux getReadableDatabase () et getWriteableDatabase (). Je savais que le vrai SQLiteOpenHelper pourrait créer un, et après avoir regardé à la source pour voir la base de données en mémoire la façon dont il est fait, je l'ai remplacé la ligne ci-dessus:

database = SQLiteDatabase.create( null );

après quoi, tout semble fonctionner. Je suis en mesure d'insérer des lignes et de les relire.

Espérons que cela aide quelqu'un d'autre.

Une chose étrange qui est arrivé à moi qui est pas exactement liée à cette question, mais pourrait aider quelqu'un plus loin, est que je suis aussi à l'aide jmockit, et je l'avais utilisé dans un essai dans la même classe; mais pour une raison quelconque, cela a causé ma classe d'ombre personnalisée pour ne pas être utilisé. Je suis passé à Mockito pour seulement cette classe, et il fonctionne très bien.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top