2011-10-06 19 views
6

Tengo una prueba para una clase DAO, utilizo DBUnit para crear y completar la base de datos (utilizando un derby en memoria). Tengo problemas al probar el método de actualización de dao porque modifica los datos y luego falla la otra prueba. Como todos sabemos, una prueba debe ser independiente de cualquier otra, y sé que DBUnit tiene algunas facilidades para limpiar y regenerar la base de datos después de cada prueba. ¡Pero no funciona!DBNo cerrar e insertar la base de datos después de cada método, por lo que las pruebas no son independientes

El código es la siguiente (TestNG):

@BeforeMethod 
public void prepareData() throws Exception { 
    cleanAndPopulate("users"); 
} 

public void cleanAndPopulate (String nameXML) throws Exception { 
    IDatabaseConnection conn; 
    conn = new DatabaseConnection (sessionForTesting.connection());   
    InputStream is = DBconnection.class.getClassLoader() 
    .getResourceAsStream(nameXML + ".xml");  
    dataset = new FlatXmlDataSet(is); 
    System.out.println("*** Preparando base de datos de test"); 
    DatabaseOperation.CLEAN_INSERT.execute(conn, dataset); 
} 

Esta es la prueba (desactivado para evitar efectos colaterales):

@Test(enabled=false) // Deja la BBDD en estado erroneo!!! 
public void busco_y_actualizo() throws Exception { 
    PacoUser resultado = userdao.getById(1L); 
    resultado.setName("OTRO"); 
    userdao.update(resultado); 
   PacoUser resultado2 = userdao.getById(1L); 
   AssertJUnit.assertNotNull(resultado2); 
    AssertJUnit.assertEquals("OTRO", resultado2.getName());    
} 
+0

¿Podría darnos más información? ¿Su método cleanAndPopulate() se ejecuta o no? – chkal

Respuesta

0

Asegúrese de que la base de datos se pone a cero antes de cada caso de prueba sola para garantizar la independencia de la prueba. @BeforeMethod solo se llama una vez antes de que se ejecuten todos los casos de prueba, por lo que poner cleanAndPopulate aquí no es suficiente.

1
@After 
public void after() throws SQLException { 
    Session session = hibernateSessionFactory.openSession(); 
    try { 
     Work work = new Work() { 

      @Override 
      public void execute(Connection connection) throws SQLException { 
       IDatabaseConnection dbConn = null; 
       try { 
        dbConn = getConnection(connection); 
       } catch (DatabaseUnitException e) { 
        logger.error("Exception in before", e); 
        Assert.fail(e.getMessage()); 
       } 

       try { 
        List<String> resultList = (List<String>) hibernateTemplate 
          .execute(new HibernateCallback() { 
           String sql = "SELECT st.TABLE_NAME FROM INFORMATION_SCHEMA.SYSTEM_TABLES st where st. TABLE_TYPE='TABLE'"; 

           public List<String> doInHibernate(
             Session session) 
             throws HibernateException, 
             SQLException { 
            Query query = session 
              .createSQLQuery(sql); 
            List<String> list = query.list(); 
            return list; 
           } 
          }); 

        QueryDataSet partialDataSet = new QueryDataSet(dbConn); 
        for (String tableName : resultList) { 
         partialDataSet.addTable(tableName); 
        } 

        DatabaseOperation.DELETE_ALL.execute(dbConn, 
          partialDataSet); 

       } catch (Exception e) { 
        logger.error("Exception in after", e); 
        Assert.fail(e.getMessage()); 
       } finally { 
        dbConn.close(); 
       } 

      } 

     }; 
     session.doWork(work); 

    } catch (Exception e) { 
     logger.error("Exception in after", e); 
     Assert.fail(e.getMessage()); 
    } finally { 
     session.close(); 
    } 
} 

protected DatabaseConnection getConnection(Connection connection) 
     throws DatabaseUnitException, SQLException { 
    return new DatabaseConnection(connection, SCHEMA); 
} 
7

Es porque CLEAN_INSERT hace "limpio" antes de la prueba, no después de la prueba.

Por ejemplo, si hay dos pruebas, test1 y test2. test1 y test2 rellenan tablas de test1.xml y test2.xml respectivamente.

test1.xml es como

<dataset> 
    <table1 ... /> 
    <table2 ... /> 
</dataset> 

test2.xml es como

<dataset> 
    <table1 ... /> 
</dataset> 

Cuando el orden de pruebas es test1 y luego test2, CLEAN_INSERT hará las siguientes operaciones:

  1. borrar todo de la tabla2
  2. borrar todo de la pestaña LE1
  3. Insertar datos desde test1.xml en tabla1
  4. Insertar datos desde test1.xml en tabla2
  5. Ejecutar test1
  6. borrar todo de la Tabla1
  7. Insertar datos desde test2.xml en tabla1
  8. ejecutar test2

Así que cuando se ejecuta test2, table1 tiene datos de test2.xml, que es lo que esperamos. Pero table2 aún contiene datos para test1, lo que puede causar algunos problemas.

Una solución alternativa es tener una fila vacía para cada tabla en todos los archivos xml. Se asegurará de que todas las tablas se limpien antes del inserto.

Para el ejemplo anterior,

test1.xml será como

<dataset> 
    <table1 ... /> 
    <table2 ... /> 
    <table1 /> 
    <table2 /> 
</dataset> 

test2.xml es como

<dataset> 
    <table1 ... /> 
    <table1 /> 
    <table2 /> 
</dataset> 
+0

Buena respuesta clara. Sorprendente, no hay una mejor solución para esto. – Hurricane

Cuestiones relacionadas