2010-05-31 168 views
3

我的JUnit测试中有一个非常奇怪的问题,我似乎无法确定。我有一个具有相当标准结构的多模块java webapp项目(DAO,服务分支等)。在这个项目中,我有一个'核心'项目,它包含一些抽象的设置代码,它将一个测试用户和必要的项目一起插入到用户中(在这种情况下是一个'企业',因此用户必须属于企业,在数据库级别)JUnit测试失败 - 抱怨刚刚插入的缺失数据

相当简单那么远,但这里是哪里的陌生感开始

  1. 一些测试无法运行,并抛出一个数据库异常的地方抱怨用户不能插入,因为企业不存在。但它只是在前面的代码行中创建了企业!企业的插入没有错误。
  2. 陌生人,但如果这个测试类本身运行一切正常。只有当测试作为项目的一部分运行时才会失败!
  3. 而完全相同的抽象代码是在失败之前通过10次测试运行的!
  4. ˚F

我一直在敲我的头靠在这个墙上的天,真的没有取得任何进展。我甚至不确定要提供哪些信息来帮助诊断此问题。

  • 使用JUnit 4.4,春季2.5.6,2.3.0的iBatis,PostgreSQL 8.3版本
  • 切换到org.springframework.jdbc.datasource.DriverManagerDataSource从org.apache.commons.dbcp.BasicDataSource改变的问题。使用DriverManagerDataSource,测试第一次工作,但现在突然间大量数据不会回滚到数据库中!它使一切落后。当通过Eclipse & Maven的

运行,请询问任何信息可以帮助我解决我的问题都没有错误

  • 测试失败!

    更新:我已经把记录打开到最大。这次失败的测试与另一次成功的测试只有一点区别。差异是突出显示的。之后发生错误我看到一些“创建[java.util.concurrent.ConcurrentHashMap中]”线,然后将错误处理代码开始

  • +0

    您可以在故障点检查数据库吗?它实际上是否有企业记录? – Yishai 2010-05-31 18:59:36

    +0

    可以给你提供你的db模型吗.. – bragboy 2010-05-31 19:01:07

    回答

    0

    嗯......我似乎偶然发现了这个问题的解决方案,虽然我真的无法把握到底是什么。我正在重建我的测试,通过全部移动它们,然后逐个恢复它们。低和看,直到我加入最后的测试类,问题再次出现

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

    所以......如果有人曾经有这个奇怪的问题,您可以尝试删除多余的注释来修复它

    1

    这是一个硬需要解决的问题,但是我会根据你提供的细节进行猜测。

    假设:测试中的插入全部发生在一个事务中,该事务被回滚。 (这就是为什么BasicDataSource保持数据库清洁的原因 - 它在最后回滚)。当停止发生时(通过使用DriverManagerDataSource)测试通过但数据库不回滚。

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

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

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

    进一步编辑:我通过调用接近终结的意思是这样的:

    public class SomeConnectionWrapper { 
         private Connection dbConnection; 
    
         protected void finalize() { 
          dbConnection.close(); 
         } 
    } 
    

    如果SomeConnectionWrapper被垃圾回收和关闭连接,数据库连接池会返回一个不同的连接。

    +0

    谢谢你的帮助易hai。一个事务如何被回滚而没有触发回滚?即根本没有错误,我不会引发回滚。 我刚把日志记录到最大值,只有一个区别,我可以看到这个失败的测试和另一个就像它。我会在一分钟后发布这些结果 – 2010-05-31 20:46:33

    +0

    @Collin,正如我所说,我正处于野外猜测的领域。可以通过几种方式在代码中触发回滚:关闭设置为“autocommit:false”的数据库连接或显式回滚。我会检查你的代码,以确定关闭连接的终结器。 – Yishai 2010-05-31 20:59:02

    +0

    结果张贴在主要问题 – 2010-05-31 20:59:24

    1

    我跑进使用Junit4和春天有类似的问题。 为了在提交之前从数据库读回内容,我必须将@Transactional添加到我的测试方法中。