Tips And Tricks JUnit Spring

0
12409

Creación: 04-08-2009

Índice de contenidos

  1. Introducción
  2. Entorno
  3. Cargar contexto de Spring en los test de JUnit
  4. JUnit, Spring y Transacciones
  5. Conclusiones
  6. Sobre el autor

1. Introducción

En este tutorial vamos a contar un par de trucos bastante útiles a la hora de hacer test usando JUnit y Spring.

La verdad es que no son nada del otro mundo, y son cosas que podemos encontrar en la documentación de Spring, pero muchas veces las olvidamos y nos dan quebraderos de cabeza 😉

También aviso que este tutorial va dirigido a aquellos que ya conocen JUnit y Spring. Los que no tengáis estos conocimientos, lo siento mucho pero este tutorial seguramente os sonará a chino. En tal caso os recomiendo visitar otros tutoriales que podéis encontrar, como:

2. Entorno

El tutorial está escrito usando el siguiente entorno:

  • Hardware: Portátil MacBook Pro 17′ (2.93 GHz Intel Core 2 Duo, 4GB DDR3 SDRAM, 128GB Solid State Drive).
  • NVIDIA GeForce 9400M + 9600M GT with 512MB
  • Sistema Operativo: Mac OS X Leopard 10.5.6

3. Cargar contexto de Spring en los test de JUnit

Cuando usamos la anotación @ContextConfiguration(locations = { «classpath:applicationContext-test.xml» }) Spring internamente guarda el contexto en una cache, donde la clave es la lista de ficheros que le hemos pasado (el atributo locations).

Esto significa que si tenemos dos clases de test (cada clase de test tendrá n métodos marcados con la anotación @Test) con la misma locations, la segunda clase no cargará el contexto y se utilizará el que ya está cargado de la primera clase de test.

Esto implica que si estamos haciendo test de integración, y en el contexto estamos usando una base de datos, como HSQLDB (http://hsqldb.org/), la segunda clase no volverá a levantar la base de datos, y usara la base de datos tal cual la dejará la primera clase de test.

Ahora imaginemos que tenemos tres test:

  • El primero usa una locations={ «classpath:applicationContext-cargaHSQLDB.xml», «classpath:otroApplicationContext.xml» }
  • El segundo usa una locations={ «classpath:applicationContext-cargaHSQLDB.xml» }
  • El tercero vuelve a usar una locations={ «classpath:applicationContext-cargaHSQLDB.xml», «classpath:otroApplicationContext.xml» }

¿Qué es lo que va a pasar?

  1. El primer test cargará el contexto resultado de los dos ficheros, cargando la base de datos. Y el contexto se guarda en la cache.
  2. El segundo test, como el locations es distinto, volverá a crear un contexto (esta vez usando un solo fichero) y por lo tanto volverá a cargar la base de datos, machacando la que ya teníamos preparada del primer test. El contexto se guarda en la cache.
  3. El tercer test lo más seguro es que falle, esto es porque como el locations está en la cache, NO se vuelve a crear el contexto, se utiliza el del primer test, esto hace que NO se vuelva a crear la base de datos, usando la del primer test, pero esta ya no es correcta porque la machacó el segundo test.

Así que ojo con los locations 😉

4. JUnit, Spring y Transacciones

En muchos casos marcamos los métodos de test como @Transactional. De esta forma nos aseguramos de que durante todo el test (método de test) existe una única sesión (evitando posibles lazy inicialization exception) y que todas las operaciones se realizan dentro de la misma transacción.

Pues bien, Spring, automáticamente, hace rollback de todas las operaciones al terminar el test, por lo que si hemos hecho modificaciones en la base de datos, estas no tendrán efecto en el resto de los test.

Esto en principio tiene bastante sentido, ya que la idea es que la ejecución de un test (método de test) debe ser independiente del resto de los test, y que no debe importar el orden de ejecución de los mismos. Pero en determinadas ocasiones nos puede interesar que las modificaciones que hace un test sobre la base de datos, se queden visibles para los test siguientes (Ojo, repito que esta práctica no sería recomendable, siendo preferible la total independencia entre los test).

Así que si queremos que se haga commit al terminar la transacción, podemos cambiar este comportamiento por defecto, con las siguientes anotaciones:

  • @TransactionConfiguration(defaultRollback=false) es una anotación que se pone a nivel de clase, y que hace que no se haga rollback después de ninguna transacción.
  • @Rollback(false) es una anotación a nivel de método que indica que no se debe hacer rollback al terminar la transacción de este método (método anotado con @Transactional)

5. Conclusiones

Siempre os insisto en lo importante que es leer atentamente la documentación de los componentes que usamos en nuestros desarrollos. Esta no es una excepción, y se ve como nos podemos evitar errores extraños, causados por un mal entendimiento y uso de las herramientas a nuestro alcance.

6. Sobre el autor

Alejandro Pérez García, Ingeniero en Informática (especialidad de Ingeniería del Software) y ScrumMaster

Socio fundador de Autentia (Formación, Consultoría, Desarrollo de sistemas transaccionales)

mailto:alejandropg@autentia.com

Autentia Real Business Solutions S.L. – «Soporte a Desarrollo»

http://www.autentia.com

 

Dejar respuesta

Please enter your comment!
Please enter your name here