2011-10-06 11 views
6

Mam test dla klasy DAO, używam DBUnit do tworzenia i zapełniania bazy danych (przy użyciu derby w pamięci). Występują problemy podczas testowania metody aktualizacji dao, ponieważ powoduje ona modyfikację danych, a drugi test kończy się niepowodzeniem. Jak wszyscy wiemy, test powinien być niezależny od jakiegokolwiek innego i wiem, że DBUnit ma pewne możliwości czyszczenia i regeneracji bazy danych po każdym teście. Ale to nie działa!DBUnit nie czyszczenia i wstawiania bazy danych po każdej metodzie, więc test nie są niezależne

Kod jest to (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); 
} 

To jest test (wyłączone, aby uniknąć skutków zabezpieczenia):

@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

Czy możesz podać więcej informacji? Czy twoja metoda cleanAndPopulate() jest wykonywana czy nie? – chkal

Odpowiedz

0

upewnić się, że baza danych jest zresetowana przed każdym pojedynczym przypadku testowego w celu zapewnienia niezależności testu. @BeforeMethod jest wywoływany tylko raz, zanim wszystkie testy zostaną uruchomione, więc umieszczenie tutaj cleanAndPopulate nie wystarczy.

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

Dzieje się tak, ponieważ CLEAN_INSERT wykonuje "CZYSTE" przed testem, a nie po teście.

Na przykład, jeśli istnieją dwa testy, test1 i test2. test1 i test2 wypełniają odpowiednio tabele z test1.xml i test2.xml.

test1.xml jest jak

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

test2.xml jest jak

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

Gdy kolejność testów jest test1 i test2, CLEAN_INSERT zrobi następujące operacje:

  1. usunąć wszystkie z tabeli2
  2. usunąć wszystkie z zakładki LE1
  3. dane Wstaw z test1.xml język tabela1
  4. danych Wstaw z test1.xml język Table2
  5. wykonywać test1
  6. usunąć wszystkie z tabela1
  7. dane Wstaw z test2.xml do tabela1
  8. wykonać test2

Kiedy test2 jest wykonywany, tabela 1 zawiera dane z pliku test2.xml, czego oczekujemy. Jednak tabela 2 nadal zawiera dane dla testu 1, co może powodować pewne problemy.

Obejście problemu polega na umieszczeniu pustego wiersza dla każdej tabeli we wszystkich plikach xml. Upewni się, że wszystkie tabele zostaną wyczyszczone przed wstawieniem.

W powyższym przykładzie,

test1.xml będzie jak

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

test2.xml jest jak

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

Ładna, jasna odpowiedź. Zaskakujące, że nie ma lepszego rozwiązania. – Hurricane

Powiązane problemy