DBUnit не очищает и вставляет базу данных после каждого метода, поэтому тестирование не является независимым - PullRequest
7 голосов
/ 06 октября 2011

У меня есть тест для класса DAO, я использую DBUnit для создания и заполнения базы данных (используя дерби в памяти). У меня проблемы при тестировании метода обновления dao, потому что он изменяет данные, а затем другой тест не проходит. Как все мы знаем, тест должен быть независимым от любого другого, и я знаю, что DBUnit имеет некоторые средства для очистки и регенерации базы данных после каждого теста. Но это не работает!

Код такой (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); 
}

Это тест (отключен, чтобы избежать побочных эффектов):

@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());    
}

Ответы [ 3 ]

9 голосов
/ 20 мая 2015

Это потому, что CLEAN_INSERT делает "CLEAN" перед тестом, а не после теста.

Например, если есть два теста, test1 и test2. test1 и test2 заполняют таблицы из test1.xml и test2.xml соответственно.

test1.xml похож на

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

test2.xml похож на

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

Когда порядок тестов - test1, а затем test2, CLEAN_INSERT выполнит следующие операции:

  1. удалить все из таблицы2
  2. удалить все из таблицы1
  3. вставить данные из test1.xml в table1
  4. вставить данные из test1.xml в table2
  5. выполнить тест1
  6. удалить все из таблицы1
  7. вставить данные из test2.xml в table1
  8. выполнить тест2

Таким образом, при выполнении test2 таблица table1 получает данные из test2.xml, чего мы и ожидаем. Но таблица2 по-прежнему содержит данные для test1, что может вызвать некоторые проблемы.

Обходной путь должен иметь пустую строку для каждой таблицы во всех XML-файлах. Перед вставкой все таблицы будут очищены.

Для приведенного выше примера,

test1.xml будет похож на

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

test2.xml похож на

<dataset>
  <table1 ... />
  <table1 />
  <table2 />
</dataset> 
1 голос
/ 25 июня 2013
@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);
}
0 голосов
/ 12 марта 2012

Убедитесь, что база данных сбрасывается перед каждым тестом, чтобы обеспечить независимость теста. @BeforeMethod вызывается только один раз перед запуском всех тестовых случаев, поэтому недостаточно ввести cleanAndPopulate.

...