2011-10-06 21 views
6

我有一个DAO类的测试,我使用DBUnit来创建和填充数据库(使用内存中的derby)。 我在测试dao更新方法时遇到问题,因为它修改数据,然后其他测试失败。正如我们所有人都知道测试应该独立于其他任何测试,并且我知道DBUnit在每次测试后都有一些工具可以清理和重新生成数据库。 但它不起作用!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

你能否提供一些信息?您的cleanAndPopulate()方法是否执行? – chkal

回答

0

确保数据库的每一个测试用例之前重置确保测试的独立性。在所有测试用例运行前,@BeforeMethod只会调用一次,所以在这里输入cleanAndPopulate是不够的。

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

这是因为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. 全部从表格中删除从test1.xml LE1
  3. 将数据插入表1从test1.xml
  4. 将数据插入表2
  5. 执行test1的
  6. 从表1从test2.xml
  7. 插入数据删除所有到table1的
  8. 执行test2

所以当test2被执行时,table1有来自test2.xml的数据,这正是我们所期望的。但是table2仍然包含test1的数据,这可能会导致一些问题。

解决方法是在所有xml文件中的每个表中都有一个空行。它会确保在插入之前清理所有表格。

对于上面的例子,

test1.xml会像

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

TEST2。xml就像

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

很明确的答案。令人惊讶的是没有更好的解决方案。 – Hurricane

相关问题