Prueba de base de datos SQLite en Robolectric
Estoy tratando de probar una base de datos SQLite simple usando Robolectric en mi aplicación de Android. Estoy poniendo algunos valores, pero al leerlos se devuelven 0 filas.
Estoy utilizando la clase SQLiteOpenHelper para acceder a la base de datos.
- Conexión de SQLite se filtró aunque todo se cerró
- Seguridad de base de datos Sqlite
- en un Listview en el artículo de la lista chasquido ¿cómo puedo conseguir el título (el nombre) del artículo seleccionado? androide
- Android NullpointerException al intentar recuperar datos de SQLiteOpenHelper
- Guardar ArrayList en la base de datos SQLite en Android
// 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 usando Robolectric?
- nativescript-sqlite y módulo angular2 no se encuentra excepción
- ¿Necesito llamar a getWritableDatabase () cada vez que manipulo datos
- Sugar ORM No hay tal tabla de excepción
- Cómo evitar objetos duplicados en la base de datos DB4o
- La aplicación no cerró el cursor o el objeto de base de datos que se abrió aquí:
- La base de datos SQLite ..onCreate () no se está llamando
- ¿Cuál es la forma correcta de hacer inserciones / actualizaciones / eliminaciones en Android SQLiteDatabase utilizando una cadena de consulta?
- Mejor alternativa de la librería Android de SQLite?
NOTA: Esta respuesta está obsoleta. Si está utilizando RoboLight 2.X, consulte https://stackoverflow.com/a/24578332/850787
El problema es que la base de datos SQLiteDatabase de Robolectric se almacena sólo en la memoria, por lo que cuando llama a getReadableDatabase o getWritableDatabase, la base de datos existente se reemplazará con nueva base de datos vacía.
Estaba funcionando al mismo problema y la única solución que encontré era que necesitaba fork el proyecto de Robolectric y agregado ShadowSQLiteOpenHelper para ahorrar la base de datos si el mismo contexto se da dos veces. Sin embargo el problema con mi tenedor es que tuve que 'disable' close () – función cuando se da el contexto porque de lo contrario Connection.close () destruirá la base de datos en la memoria. He hecho la petición del tirón para ella pero no se ha combinado al proyecto todavía.
Pero siéntase libre de clonar mi versión y debería solucionar su problema (si lo entendí correctamente: P). Se puede encontrar en GitHub: https://github.com/waltsu/robolectric
He aquí 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 que no es necesario crear nuevo SQLiteOpenHelper, pero eso es sólo el ejemplo que pasando el mismo contexto a dos diferentes SQLiteOpenHelper dará la misma base de datos.
Robolectric 2.3 utiliza una implementación real de SQLite en lugar de una colección de sombras y falsificaciones. Ahora se pueden escribir pruebas para verificar el comportamiento real de la base de datos.
El código vinculado en la respuesta aceptada no funcionó para mí; Puede ser anticuado. O tal vez mi configuración es diferente. Estoy utilizando Robolectric 2.4 instantánea, que no parece incluir un ShadowSQLiteOpenHelper, a menos que me faltó algo. En cualquier caso, descubrí una solución. Esto es lo que hice:
- Creé una clase llamada ShadowSQLiteOpenHelper y copié el contenido del código enlazado arriba ( https://github.com/waltsu/robolectric/blob/de2efdca39d26c5f18a3d278957b28a555119237/src/main/java/com/xtremelabs/robolectric/shadows/ShadowSQLiteOpenHelper. Java ), y fijó las importaciones.
- Siguiendo las instrucciones en http://robolectric.org/custom-shadows/ para usar sombras personalizadas,
@Config( shadows = { ShadowSQLiteOpenHelper.class } )
mi clase de prueba con@Config( shadows = { ShadowSQLiteOpenHelper.class } )
. No hay necesidad de un corredor de pruebas personalizado. - En mis pruebas, instancié mi subclase de SQLiteOpenHelper, pasando en una
new Activity()
como el Contexto (Robolectric felizmente se ocupa de eso), y lo usé por costumbre.
Ahora, en este punto, me di cuenta de que un archivo de base de datos real se estaba creando localmente: después de la primera ejecución de una prueba que utiliza mi subclase SQLiteOpenHelper, seguí recibiendo 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 estaba bajo 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 shadow es:
database = SQLiteDatabase.openDatabase( "path", null, 0 );
En getReadableDatabase () y getWriteableDatabase (). Yo sabía que el verdadero SQLiteOpenHelper podría crear una base de datos en la memoria, y después de mirar la fuente para ver cómo se hace, he reemplazado la línea anterior con:
database = SQLiteDatabase.create( null );
Después de lo cual, todo parece funcionar. Puedo insertar filas y leerlas de nuevo.
Espero que esto ayude a alguien más.
Una cosa extraña que me pasó 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 utilizado en una prueba en la misma clase; Pero por alguna razón, esto hizo que mi clase de sombra personalizada no se utilizara. Cambié a Mockito por esa clase, y funciona bien.
- Reintentar la solicitud utilizando Retrofit 2
- La conversión al formato de Dalvik falló con error 1 – Exportación de APK