DBUnit

RECU-0249 (Recurso Ficha Técnica)

Descripción

DBUnit es una extensión de JUnit para realizar test unitarios que permiten interactuar con un conjunto de datos. También permite dejar la base de datos en un estado conocido, antes y después de cada test, con el fin de prevenir que datos corruptos, producto de test fallidos, queden en la base de datos ocasionando problemas a los test siguientes.

Su principal función es controlar el estado de la base de datos al realizar las pruebas, para así solucionar dos de los problemas que se dan más a menudo: Comprobar que los datos que se esperan en la base de datos son los correctos y preservar los datos de un test a otro (dado que un test puede corromper los datos del siguiente test, etc.).

Para realizar su función, DBUnit se basa en un sistema de importación/exportación de los datos de la base de datos a un fichero XML. Además, desde la versión 2.0, puede manejar grandes cantidades de datos cuando se usa en modo streaming.

Los componentes principales son:

  • IDatabaseConnection: Interfaz que representa una conexión DBUnit a la base de datos.
  • IDataSet: Interfaz que representa una colección de tablas (Manipula tablas y datos).
  • DatabaseOperation: Clase abstracta que representa la operación que se va a realizar sobre la base de datos antes o después de un test.

El procedimiento básico para realizar un test es el siguiente:

  1. Creamos el DataSet de la prueba, preferiblemente en XML
  2. Configurar la conexión a la base de datos en @BeforeClass
  3. Inicializar la base de datos de pruebas con los datos de pruebas con FlatXmlDataSet en @BeforeClass
  4. Poner la base de datos a un estado definido en @before usando DatabaseOperation
  5. Ejecutar el código a probar en @Test y verificar los resultados obtenidos
  6. Cerciorarse de verificar que no hay efectos no deseados y volver al estado definido en la base de datos en @After usando DatabaseOperation
  7. Eliminar las conexiones con la base de datos en @AfterClass

Ejemplo de uso

import java.util.List;   
 
import javax.annotation.Resource;  
 
import org.junit.AfterClass;  
import org.junit.Assert;  
import org.junit.BeforeClass;  
import org.junit.Test;  
import org.junit.runner.RunWith;  
import org.springframework.test.context.ContextConfiguration;  
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;  
import org.springframework.test.context.transaction.TransactionConfiguration;  
import org.springframework.transaction.annotation.Transactional;  
 
import com.madeja.dbunit.persistence.entity.WebUsuarios;  
import com.madeja.dbunit.persistence.entity.WebDirecciones;  
import com.madeja.dbunit.persistence.entity.WebPaises;  
import com.madeja.dbunit.persistence.Dao;  
 
 
@RunWith(SpringJUnit4ClassRunner.class)  
@ContextConfiguration(locations = { "classpath:applicationDBUniContext-test.xml" })  
@TransactionConfiguration(transactionManager = "transacctionManager", defaultRollback = false)  
@Transactional 
public class DbUnitTest {  
 
    @Resource 
    private Dao dao;  
 
    @BeforeClass 
    public static void startUp() {  
 
        try {  
          DBUnitUtils.generateXML("org.postgresql.Driver",  
                              "jdbc:postgresql://localhost:5432/dbunit",  
                              "postgres",  
                                        "postgres",  
                              "public",  
                              "dbUnit");  
            DBUnitUtils.createData("org.hsqldb.jdbcDriver",  
                                       "jdbc:hsqldb:file:/tmp/appName/db/hsqldb/hibernate;shutdown=true",  
                             "sa",  
                             "",  
                             "dbUnit");  
 
        } catch (Exception e) {  
            // TODO Auto-generated catch block  
            e.printStackTrace();  
        }  
 
    }  
 
    @AfterClass 
    public static void tearDown() {  
 
        try {  
            DBUnitUtils.deleteData("org.hsqldb.jdbcDriver",  
                                       "jdbc:hsqldb:file:/tmp/appName/db/hsqldb/hibernate;shutdown=true",  
                             "sa",  
                             "",  
                             "dbUnit");  
        } catch (Exception e) {  
            // TODO Auto-generated catch block  
            e.printStackTrace();  
        }  
 
    }  
 
    @Test 
    public void test1() {  
 
        // Comprueba que la tabla de países contenga datos  
        List<WebPaises> paises = dao.loadAll(WebPaises.class);  
        Assert.assertTrue(paises != null);  
        Assert.assertTrue(paises.size() > 0);  
 
    // Comprueba que la tabla de direcciones contenga datos  
        List<WebDirecciones> direcciones = dao.loadAll(WebDirecciones.class);  
        Assert.assertTrue(direcciones != null);  
        Assert.assertTrue(direcciones.size() > 0);  
          
        // Comprueba que la tabla de usuarios contenga datos  
        List<WebUsuarios> usuarios = dao.loadAll(WebUsuarios.class);  
        Assert.assertTrue(usuarios != null);  
        Assert.assertTrue(usuarios.size() > 0);  
 
 
    }  
}

Uso y recomendaciones conocidas

  • Recomendado en el Framework AMAP del Consejo de Cantabría
  • Importante soporte de la comunidad de desarrolladores

Requisitos e incompatibilidades

  • No es útil para verificar consultas, ya que éstas no alteran la base de datos y, además, se pueden verificar por los métodos tradicionales pero, aún así, DBUnit se puede usar para cargar los datos ficticios a consultar sin alterar la base de datos.
  • El tratamiento de las claves ajenas que apuntan a id's autogenerados es difícil y tedioso de manejar. Esta parte no está muy conseguida en el framework todavía.
  • slf4j-api-1.5.2.jar
  • slf4j-simple-1.5.2.jar
  • Dependencia completa con JUnit

Contenidos relacionados

Pautas
Área: Desarrollo » Librerías y Módulos » Java
Código Título Tipo Carácter
LIBP-0344 Librerías para aplicaciones Java Libro de pautas Directriz Recomendada