JUnit测试失败 - 抱怨刚刚插入的数据丢失

时间:2010-05-31 18:54:25

标签: java spring transactions ibatis

我的JUnit测试中有一个非常奇怪的问题,我似乎无法确定。我有一个具有相当标准结构的多模块java webapp项目(DAO,服务clasess等...)。在这个项目中,我有一个'核心'项目,其中包含一些抽象的设置代码,用于插入测试用户以及用户必需的项目(在这种情况下是'企业',因此用户必须属于企业并且这是强制执行的在数据库级别)

到目前为止相当简单......但这里是陌生感开始的地方

  1. 某些测试无法运行并抛出数据库异常,因为它抱怨由于企业不存在而无法插入用户。但它只是在前面的代码行中创建了企业!并且企业的插入没有错误。
  2. 更奇怪的是,如果这个测试类是自己运行的,那么一切正常。只有当测试作为项目的一部分运行时才会失败!
  3. 完全相同的抽象代码在失败之前由10多个测试运行!
  4. ˚F
  5. 我这几天一直用头撞墙,并没有取得任何进展。我甚至不确定提供哪些信息来帮助诊断这个问题。

    • 使用JUnit 4.4,Spring 2.5.6,iBatis 2.3.0,Postgresql 8.3
    • 从org.apache.commons.dbcp.BasicDataSource切换到org.springframework.jdbc.datasource.DriverManagerDataSource更改了问题。使用DriverManagerDataSource,测试第一次工作,但现在突然间很多数据没有回滚到数据库中!它抛弃了一切。全部没有错误
    • 通过Eclipse& amp;运行时测试失败行家

    请询问任何可以帮助我解决问题的信息!

    更新:我已将日志记录调到最大。这个失败的测试和另一个失败的测试之间只有一点点差别。突出显示了差异。发生错误后,我看到一些“Creating [java.util.concurrent.ConcurrentHashMap]”行,然后错误处理代码开始

3 个答案:

答案 0 :(得分:1)

这是一个难以解决的问题,但我会根据您提供的详细信息进行猜测。

假设:测试中的插入都发生在事务中,后者被回滚。 (这就是为什么BasicDataSource使数据库保持干净 - 它最后回滚)。当停止发生时(通过使用DriverManagerDataSource),测试通过,但数据库不会回滚。

这表明即使“它只是在前一行代码中创建了企业!”可以回滚事务以删除记录。

进一步的假设(好吧,过度说明,尝试疯狂猜测),某些东西(在BasicDataSource中或更可能是你自己的框架代码)在终结器中调用事务的回滚。这就是为什么它工作10次以上然后失败,并且只作为项目的一部分 - 它是那个在那时触发垃圾收集的运行,导致事务回滚,导致新的代码行开始新的事务记录处于无效状态。

编辑:从您的编辑开始,似乎由于某种原因,在失败的测试中您获得了新的数据库连接。这符合我上面的场景,但也可以通过声明由于某种原因在代码中的某些原因在测试作为整个项目的一部分运行时获得新事务来解释。新事务看不到在不同事务中发生的企业记录的插入,并且事务保持打开和未提交。测试的一种方法是将此运行时的事务隔离级别设置为最大值,以便在其上有事务时不会扫描企业表。如果这种情况正确,那么你的代码就会死锁。

进一步编辑:调用close的终结器的意思是这样的:

 public class SomeConnectionWrapper {
      private Connection dbConnection;

      protected void finalize() {
           dbConnection.close();
      }
 }

如果SomeConnectionWrapper被垃圾收集并且连接关闭,则数据库连接池将返回不同的连接。

答案 1 :(得分:1)

我使用Junit4和spring遇到了类似的问题。 我必须将@Transactional添加到我的测试方法中,以便在提交之前从数据库中读回内容。

答案 2 :(得分:0)

好吧......我似乎偶然发现了解决这个问题的方法,尽管我无法确切地指出它究竟是什么。我正在通过移动它们来重建我的测试,然后逐个恢复它们。低,看到直到我添加最终测试类,问题再次出现

此测试类从基本测试类扩展,该类定义了所有与Spring相关的设置注释,如@ RunWith和@ContextConfiguration。由于某种原因,这个测试类重新定义了@RunWith和@ContextConfiguration属性,一旦我删除它们,事情就开始重新开始了。关于这个测试类的另一个奇怪的事情是我在每个测试中使用@Ignore(它包含一些旧的测试)。

所以...如果有人遇到这个奇怪的问题,你可以尝试删除额外的注释来修复它