Pregunta

Estoy tratando de probar una base de datos SQLite simple utilizando Robolectric en mi aplicación Android. Estoy poniendo algunos valores, pero al leerlos se devuelven, se devuelven 0 filas.

Estoy usando la clase SQLiteOpenHelper para acceder a la base de datos.

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

Al depurar el código fuera de Robolectric, esto funciona como se esperaba. ¿Estoy haciendo algo malo o no es posible probar bases de datos SQLite utilizando robolectric?

¿Fue útil?

Solución

Nota: Esta respuesta está desactualizada. Si está utilizando Roboletric 2.x, consulte https://stackoverflow.com/a/24578332/850787

El problema es que la SQLitedAtabase de Robolectric se almacena solo en la memoria, por lo que cuando llame a GetReapedAdatabase o GetWritableAdAbase, la base de datos existente se anulará con una nueva base de datos vacía.

Estaba ejecutando el mismo problema y la única solución que encontré era que necesitaba desembolsar el proyecto robolectric y agregar ShadowsqliteOpenHelper para guardar la base de datos si el mismo contexto se da dos veces. Sin embargo, el problema con mi bifurcación es que tuve que 'deshabilitar' cerrar ()-función cuando se da el ámbito porque de lo contrario Connection.close () destruirá la base de datos en la memoria. He hecho una solicitud de extracción, pero aún no se ha fusionado con el proyecto.

Pero no dude en clonar mi versión y debe solucionar su problema (si lo entendí correctamente: P). Se puede encontrar en GitHub: https://github.com/waltsu/robolectric

Aquí hay un ejemplo de cómo usar la modificación:

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 

Por supuesto, no necesita crear un nuevo sqliteopenhelper, pero eso es solo un ejemplo de que pasar el mismo contexto a dos sqliteopenhelper diferentes dará la misma base de datos.

Otros consejos

Roboléctrico 2.3 Utiliza una implementación real de SQLite en lugar de una colección de sombras y falsificaciones. Las pruebas ahora se pueden escribir para verificar el comportamiento de la base de datos real.

El código vinculado en la respuesta aceptada no funcionó para mí; Puede estar desactualizado. O tal vez mi configuración es simplemente diferente. Estoy usando una instantánea Robolectric 2.4, que no parece incluir un ShadowsqliteOpenHelper, a menos que me perdiera algo. En cualquier caso, descubrí una solución. Esto es lo que hice:

  1. Creé una clase llamada ShadowsqliteOpenHelper y copié el contenido del código vinculado anteriormente (https://github.com/waltsu/robolectric/Blob/de2efdca39D26C5F18A3D278957B28A555119237/SRC/MAIN/JAVA/COM/XtrEMELABS/ROBOLECTRIC/SHADOWS/SHADOWSQLITEPENHELPER.JAVE), y fijó las importaciones.
  2. Siguiendo las instrucciones en http://robolectric.org/custom-shadows/ Para usar sombras personalizadas, anoté mi clase de prueba con @Config( shadows = { ShadowSQLiteOpenHelper.class } ). No hay necesidad de un corredor de prueba personalizado.
  3. En mis pruebas, instancié mi subclase de sqliteopenhelper, pasando en un new Activity() Como el contexto (Robolectric se encarga feliz de eso), y lo usó como de costumbre.

Ahora, en este punto, noté que un archivo de base de datos real se estaba creando localmente: después de la primera ejecución de una prueba que usaba mi subclase SqliteOpenHelper, seguía obteniendo una SqliteException en las pruebas posteriores porque mi tabla ya existía; Y pude ver un archivo llamado "Path" y un archivo llamado "Path-Journal" sentado en mi repositorio local. Esto me confundió porque tenía la impresión de que la clase de sombra estaba usando una base de datos en memoria.

Resulta que la línea ofensiva en la clase de sombra es:

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

en ambos getReadActiveAtabase () y getWriteAbledAtabase (). Sabía que el verdadero sqliteopenhelper podría crear una base de datos en memoria, y después de mirar la fuente para ver cómo se hace, reemplacé la línea anterior con:

database = SQLiteDatabase.create( null );

Después de lo cual, todo parece funcionar. Puedo insertar filas y leerlas.

Ojalá esto ayude a alguien más.

Una cosa extraña que me sucedió que no está exactamente relacionada con esta pregunta, pero podría ayudar a alguien más, es que también estoy usando JMockit, y lo había usado en una prueba en la misma clase; Pero por alguna razón, esto hizo que mi clase de sombra personalizada no se usara. Cambié a Mockito solo para esa clase, y funciona bien.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top