【问题标题】:DBUnit not cleaning and insert the database after every method, so test are not independentDBUnit 在每个方法之后都没有清理和插入数据库,所以测试不是独立的
【发布时间】:2011-12-02 00:11:37
【问题描述】:

我有一个 DAO 类的测试,我使用 DBUnit 创建和填充数据库(使用内存中的 derby)。 我在测试 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());    
}

【问题讨论】:

  • 您能提供更多信息吗?你的 cleanAndPopulate() 方法是否执行了?

标签: java tdd testng dbunit


【解决方案1】:

这是因为 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. 从 table2 中删除所有内容
  2. 从 table1 中删除所有内容
  3. 将 test1.xml 中的数据插入到 table1 中
  4. 将 test1.xml 中的数据插入到 table2 中
  5. 执行测试1
  6. 从 table1 中删除所有内容
  7. 将 test2.xml 中的数据插入 table1
  8. 执行测试2

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

一种解决方法是为所有 xml 文件中的每个表设置一个空行。它将确保在插入之前清理所有表。

对于上面的例子,

test1.xml 会像

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

test2.xml 就像

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

【讨论】:

  • 很好的明确答案。令人惊讶的是,没有更好的解决方案。
【解决方案2】:
@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);
}

【讨论】:

    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 2017-04-09
      • 2010-09-30
      • 1970-01-01
      • 2023-01-11
      • 1970-01-01
      • 1970-01-01
      • 2011-10-19
      • 2021-12-28
      • 1970-01-01
      相关资源
      最近更新 更多