¿Cuáles son algunas de las mejores prácticas para poblar y usar una base de datos de prueba?

8

Entonces, estoy desarrollando algunos servicios web RESTful Java basados ​​en bases de datos, usando Hibernate y MySQL. Para fines de prueba, estoy usando la base de datos H2 en memoria. H2 es agradable y rápido, por lo que esto ha funcionado muy bien. El único problema es que llenar las tablas de DB antes de mis pruebas es algo tedioso. Básicamente creo y persisto un montón de objetos a mano. Me pregunto si tal vez voy por el camino equivocado.

Por favor, dime, ¿cuáles son las mejores prácticas para hacer lo que intento hacer? ¿Alguna herramienta que pueda ayudarme? ¿Alguna estrategia general o consejos?

sangre fría
fuente

Respuestas:

4

Asumiré que ha diseñado su API para que pueda DI los detalles de su base de datos, de lo contrario, podemos ayudarlo con eso.

En términos de terminología, desea utilizar un doble de prueba falsa . En este caso particular, recomendaría usar el mismo DB en memoria (H2), pero use DBUnit para trabajar con JUnit para crear sus tablas, llenarlas antes de cada prueba, truncar los datos después de cada prueba y finalmente desmontarlos las tablas una vez que TestSuite haya finalizado.

Hay otras soluciones, como Grails y Spring Roo, que crean algunos datos de prueba para usted, pero DBUnit será un placer para usted ahora.

Martijn Verburg
fuente
+1 para DBUnit. Hace que las pruebas unitarias del código DB sean mucho más agradables.
TMN
Genial, definitivamente lo comprobaré. En este momento, le digo a Hibernate que cree automáticamente las tablas, usando la propiedad hibernate.hbm2ddl.auto = create-drop. ¿Funcionará con DBUnit o debería dejar de hacerlo?
sangfroid
Funcionará con eso, sí, de hecho, una de las formas de imitar DBUnit es simplemente insertar datos como POJO a través de Hibernate
Martijn Verburg
¡Increíble! Bien, voy a revisar esto.
sangfroid
Además, ¿es necesario usar DI para esto? En este momento tengo un persistance.xml en mi carpeta / main / resources / META-INF que especifica mi servidor de base de datos aguda, y un persistance.xml en mi carpeta / test / resources / META-INF que especifica H2. Esto parece funcionar muy bien. En general, estoy súper ultra 100% confundido acerca de Spring: nunca lo he usado antes y no entiendo cómo podría ayudarme aquí, a pesar de que todos dicen que debería usarlo.
sangfroid
1

¿Quizás se beneficiaría al utilizar un marco burlón en sus pruebas unitarias automatizadas?

Hay varios diferentes para elegir:

maple_shaft
fuente
Sí, ya uso Mockito para pruebas unitarias. Pero también quiero hacer pruebas (¿de integración?) Que lleguen a la base de datos.
sangfroid
+1 por sugerir marcos burlones sobre soluciones de bases de datos. El enfoque de la base de datos introduce con frecuencia una complejidad innecesaria que generalmente termina probando Hibernate en lugar de sus DAO. Además, agregaría JMockit en esa lista: hace todo . Cadena inmutable? No lo creo.
Gary Rowe
1
Bueno, debo mencionar que soy nuevo en Hibernate. Por lo tanto, es importante para mí probar que he hecho todas mis cosas de hibernación correctamente. Además, parece que muchas operaciones no se pudieron probar con un marco burlón. Por ejemplo, tiene un método que devuelve un montón de registros. ¿Cómo puede probar que ese método en realidad devuelve un montón de registros si no tiene una base de datos para ejecutar?
sangfroid
@sangfroid, este es un buen punto y algo de lo que me puedo beneficiar también. La lógica de Hibernate y las consultas HQL específicamente no prueban bien la unidad en el sentido tradicional. En el pasado dependía de las pruebas de unidades de integración para verificar la funcionalidad, pero estas eran casi siempre específicas del entorno y frágiles. DBUnit fue mencionado en una respuesta anterior y parece que merece una segunda mirada.
maple_shaft
1

Todo lo que realmente puede hacer es conservar los objetos a mano o tener una base de datos preconstruida que cargue. También debe asegurarse de que la base de datos se restablezca después de cada prueba.

En un proyecto en el que estoy trabajando, soy nuevo en Hibernate, así que tengo un montón de pruebas para relaciones básicas y operaciones en cascada. Usando TestNG tengo una GenericHbTestclase desde la cual se extienden todas las pruebas de Hibernate. Tiene un @BeforeMethodmétodo que reexporta el esquema db y algunos métodos de utilidad para generar varios objetos DAO. Esto me permite adaptar un entorno para cada prueba.

La única desventaja de volver a exportar el esquema en cada prueba es que lleva mucho tiempo terminar de ejecutar las pruebas. Pero solo necesito asegurarme de que todo esté separado y limpio. Si tienes más experiencia con Hibernate y tienes un esquema más estable, entonces reexportar antes de cada prueba probablemente sea innecesario. Al menos, despeje todas las tablas de antemano

TheLQ
fuente
1

¿Has considerado la serialización de objetos? Este es el método más rápido y fácil que utilicé.

Consiste en crear el estado que desea, serializarlo en el disco. Utiliza esos archivos para llenar la base de datos en memoria que usa para sus pruebas.

Una de las ventajas es que puede editar los archivos manualmente más tarde.

Como alternativa, si está bien organizado en sus pruebas unitarias, podría crear generadores de objetos. Cuando comienzan las pruebas, se crea una instancia de la base de datos y se exporta el esquema (usando nHibernate). Los objetos se generan y se completan en la base de datos.

Este método tiene una ventaja sobre el primero: sus generadores de objetos evolucionan con su código, por lo que no necesita preocuparse por sus archivos como en la sugerencia anterior.


fuente
+1 para un enfoque interesante, pero podría ser un poco frágil.
Gary Rowe