2011-10-06 13 views
6

Ho un test per una classe DAO, utilizzo DBUnit per creare e popolare il database (utilizzando un derby in memoria). Sono in difficoltà durante il test del metodo di aggiornamento dao perché modifica i dati e quindi l'altro test ha esito negativo. Come tutti sappiamo, un test dovrebbe essere indipendente da qualsiasi altro, e so che DBUnit ha alcune strutture per pulire e rigenerare il database dopo ogni test. Ma non funziona!DBUnit non pulisce e inserisce il database dopo ogni metodo, quindi il test non è indipendente

Il codice è questo (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); 
} 

Questa è la prova (disabilitato per evitare gli effetti collaterali):

@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

Potrebbe fornire ulteriori informazioni? Il tuo metodo cleanAndPopulate() è eseguito o no? – chkal

risposta

0

Assicurarsi che il database viene ripristinato prima di ogni singolo caso di test per garantire l'indipendenza del test. @BeforeMethod viene chiamato solo una volta prima che vengano eseguiti tutti i casi di test, quindi inserire cleanAndPopulate qui non è sufficiente.

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

È perché CLEAN_INSERT fa "PULIRE" prima del test, non dopo il test.

Ad esempio, se ci sono due test, test1 e test2. test1 e test2 popolano rispettivamente le tabelle da test1.xml e test2.xml.

test1.xml è come

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

test2.xml è come

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

Quando l'ordine delle prove è test1 e quindi test2, CLEAN_INSERT farà le seguenti operazioni:

  1. elimina tutto dalla tabella2
  2. elimina tutto dalla scheda LE1
  3. Inserisci dati da test1.xml in table1
  4. Inserisci dati da test1.xml in table2
  5. eseguire test1
  6. eliminare tutto da table1
  7. Inserisci dati da test2.xml in table1
  8. eseguire test2

Quindi, quando viene eseguito test2, tabella1 ha dati da test2.xml, che è quello che ci aspettiamo. Ma table2 contiene ancora dati per test1, che potrebbe causare alcuni problemi.

Una soluzione alternativa consiste nell'avere una riga vuota per ogni tabella in tutti i file xml. Si assicurerà che tutte le tabelle vengano pulite prima di inserire.

Per l'esempio precedente,

test1.xml sarà come

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

test2.xml è come

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

Bella risposta chiara. Sorprendente non c'è una soluzione migliore a questo. – Hurricane

Problemi correlati