2009-05-05 14 views
8

Tengo una clase Pruebas unitarias que requieren una configuración bastante amplia de la base de datos antes de que se puedan ejecutar los métodos de prueba individuales. Esta configuración lleva mucho tiempo: por razones que, afortunadamente, no son relevantes para la pregunta en cuestión, necesito llenar el DB programáticamente en lugar de un volcado de SQL.Configuración y desmontaje del estado de la base de datos compleja con Hibernate/Spring/JUnit

El problema que tengo es con el desmontaje. ¿Cómo puedo deshacer fácilmente todos los cambios realizados en la fase de configuración de db?

Actualmente estoy usando la compatibilidad con Hibernate + Spring Transactional Testing, por lo que mis métodos de prueba individuales están envueltos en transacciones.

Una solución sería realizar la configuración de db dentro de cada método de prueba, de modo que la configuración de db se retrotraiga automáticamente. Sin embargo, los métodos de prueba tardarían una eternidad en ejecutarse, ya que cada método necesitaría volver a preparar la base de datos.

¿Alguna otra idea? Básicamente, estoy buscando una forma de ejecutar mi configuración de bases de datos, ejecutar mis pruebas individuales (cada una envuelta en una transacción que se retrotrae después de la ejecución) y luego retrotraer la configuración inicial de bases de datos. ¿Alguna idea sobre cómo hacer que esto funcione de forma Hibernate/Primavera/Junio? ¿Existe un comando equivalente a "soltar todas las tablas" de Hibernate?

Respuesta

7

¿Está atascado con un proveedor de base de datos específico? De lo contrario, podría usar una base de datos en memoria, como HSQLDB. Cuando termine con las pruebas, simplemente descarta el estado. Esto solo es apropiado si las tablas pueden estar vacías al comienzo del conjunto de pruebas (es decir, antes de su configuración programática).

Aún necesita crear tablas, pero si todo está perfectamente ordenado utilizando Hibernate, puede usar hbm2ddl para generar sus tablas.Todo lo que tiene que hacer es añadir lo siguiente a su prueba sesión de definición de fábrica:

<session-factory> 
    ... 
    <property name="hibernate.hbm2ddl.auto">create</property> 
    ... 
</session-factory> 

Si esta solución parece aplicable puedo más detalles sobre ella.

+0

A veces me olvido de las opciones más simples. Puntos de bonificación para usted. –

+0

Entonces, al aceptar esto como la solución, ¿eso significa que optó por la instalación/eliminación de db por prueba individual? –

+0

De hecho fui con la configuración del db una vez para un conjunto de pruebas definidas en la misma clase usando un método estático @BeforeClass Junit. Pero sería bastante fácil hacer en base por prueba con un método @Before JUnit. –

0

DNUnit que debe ayudar en este sentido. Puede crear conjuntos de datos separados para cada caso de prueba individual si lo desea.

0

DBUnit ayudará mucho con esto. En teoría, podría desactivar autocommits en JDBC, pero se pondrá pesado. La solución más obvia es utilizar DBUnit para establecer sus datos en un estado conocido antes de ejecutar las pruebas. Si por alguna razón necesita recuperar sus datos después de ejecutar las pruebas, puede consultar @AfterClass en un paquete que ejecuta todas sus pruebas, pero generalmente se considera una mejor práctica configurar sus pruebas y luego ejecutarlas, por lo que que si la prueba falla, no es solo porque no tiene un entorno de prestine debido a una falla al limpiar una prueba diferente. Usted se asegura de que cada prueba configure su entorno directamente.

+0

no haría con DBUnit ser conceptualmente equivalente a secuencias de comandos SQL que fue descartado en la pregunta? – topchef

+0

No lo mencioné específicamente en la pregunta, pero estoy familiarizado con DBUnit y lo he estado evitando porque no quería tener que mantener una gran cantidad de dispositivos de prueba DBUnit cuando era más fácil generar la base de datos programáticamente. Sin embargo, puedo morder la bala que falta una mejor solución. –

0

Una solución que quizás desee considerar es utilizar una operación de retrotracción o compensación "manual" en el desmontaje de db. Supongo (y si no lo es, debería ser un complemento trivial para las entidades de Hibernate) todas sus entidades tienen un atributo datetime create que indica cuándo se insertaron en la tabla. Su método de instalación de db debe registrar el tiempo antes que todo lo demás. Luego tiene un procedimiento bastante simple para eliminar datos para eliminar todas las entidades que se crearon después de tiempo recodificado en la configuración de db.

Por supuesto, esto no funcionará para las actualizaciones en la configuración de db ... Pero si tiene un número limitado de actualizaciones, entonces considere guardar una imagen prístina para este tipo de datos y restaurarla durante el desmontaje de db.

0

Si está trabajando con una base de datos relativamente pequeña y con un DBMS que puede hacer copias de seguridad y exportaciones relativamente rápido (como MS SQL Server), puede crear una copia de seguridad antes de las pruebas y luego restaurarla cuando todas las pruebas estén completas. Esto le permite configurar una base de datos de desarrollo/prueba y usarla como un estado inicial para todas sus pruebas.

Lo hice con JDBC nativo, ejecutando '' base de datos de respaldo '' y '' restaurar base de datos '' T-SQL en las pruebas intermedias, y funcionó razonablemente bien.

Sin embargo, este enfoque depende de tener el servidor DBMS en su máquina local (a una velocidad razonable), tener privilegios suficientes (lo cual no debería ser un problema) y el tamaño total de la base de datos que no exceda unas pocas decenas en MB, al menos en mi experiencia.

0

¿Hay alguna razón por la que deba tener una conexión a la base de datos para ejecutar las pruebas de su unidad? Parece que sería más fácil refactorizar su clase para que pueda simular la interacción con la base de datos. Puede simular clases (con algunas excepciones) así como también interfaces con EasyMock (www.easymock.org).

Si su clase depende de un estado preexistente complejo en una base de datos conectada, probablemente sería más fácil escribir pruebas de ejecución más rápidas mediante el uso de simulaciones. No sabemos cuál es el tamaño de su proyecto ni con qué frecuencia se ejecutan sus pruebas, pero el tiempo de ejecución puede ser algo en lo que pensar, especialmente en un proyecto grande.

0

Hibernate tiene una pequeña característica que está muy poco documentada y es desconocida. Puede ejecutar un script SQL durante la creación de SessionFactory justo después de la generación del esquema de la base de datos para importar datos en una nueva base de datos. Solo necesita agregar un archivo denominado import.sql en su raíz de classpath y establecer create o create-drop como su propiedad hibernate.hbm2ddl.auto.

http://in.relation.to/Bloggers/RotterdamJBugAndHibernatesImportsql

Cuestiones relacionadas