我有一个DAO类的测试,我使用DBUnit来创建和填充数据库(使用内存中的德比)。 我在测试dao update方法时遇到问题,因为它修改数据然后另一个测试失败。因为我们所有人都知道测试应该独立于任何其他测试,并且我知道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());
}
答案 0 :(得分:9)
这是因为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将执行以下操作:
因此,当执行test2时,table1包含来自test2.xml的数据,这正是我们所期望的。但是table2仍然包含test1的数据,这可能会导致一些问题。
解决方法是在所有xml文件中为每个表创建一个空行。它将确保在插入之前清理所有表。
对于上面的例子,
test1.xml就像
<dataset>
<table1 ... />
<table2 ... />
<table1 />
<table2 />
</dataset>
test2.xml就像
<dataset>
<table1 ... />
<table1 />
<table2 />
</dataset>
答案 1 :(得分: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);
}
答案 2 :(得分:0)
确保在每个测试用例之前重置数据库以确保测试独立性。 @BeforeMethod仅在所有测试用例运行之前调用一次,因此将cleanAndPopulate
放在此处是不够的。