【问题标题】:Unit test passes when marked @Transactional but fails when not标记为@Transactional 时单元测试通过但未标记时失败
【发布时间】:2012-03-26 18:40:31
【问题描述】:

这样设置 JUNIT 测试

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({ "/applicationContext.xml", "/applicationContext-security.xml" })
@TransactionConfiguration(defaultRollback = true)
@Transactional
public class BlahIntegrationTests{

 @Test
 public void testMappingsOfHugeObjectGraph(){
 }
}

我正在尝试测试我的休眠映射(注释驱动和基于 JPA)是否正确,并且当像上面那样运行时我的测试通过(只是断言创建了一个 ID)。

如果我把@Transactional 拿走,我的一些关系会出现我所期待的错误。任何人都想过为什么它在@Transactional 时没有失败?

编辑:澄清一下,在保存对象时抛出的异常是关于错误的休眠映射(它是一个非常大的对象结构,我已经把其中的一些搞砸了)

【问题讨论】:

    标签: java spring hibernate jpa junit


    【解决方案1】:

    如果您删除 @Transactional,您的测试数据库不会为另一个测试为空,因此测试不会被隔离。

    如果你有它,那么一些测试可能会通过,即使它们应该失败(正如你所描述的,或者另一个例子是如果你插入的实体与某些唯一约束重复)。

    解决方案是使用@Transactional 并注入

    @PersistenceContext
    private EntityManager em;
    

    并在从数据库中提取数据之前执行以下操作

    em.flush();
    em.clear();
    

    第一行将导致会话和数据库之间的同步(您的提供者通常会等到事务结束)。 第二行将从会话中删除所有实体,因此所有查询都将转到数据库。

    在测试之后,所有内容仍会回滚,因此您的数据库处于原始状态。

    希望对你有帮助。

    【讨论】:

    • 这确实是需要发生的冲洗。具体问题是在我的许多表中的几百列中,我知道我有一些 typeo 等,我正在使用单元测试来修复它们。现在我有一个 dao.flush() 它可以正确地找到错误。
    【解决方案2】:

    如果你去掉@Transactional,Hibernate 工厂会在其等效的自动提交模式下运行,在这种模式下,你所做的每个新访问都会生成一个全新的 Session。因此,一旦您检索到一个对象,它就会立即不再与打开的会话相关联并且没有资格进行延迟加载。

    【讨论】:

    • 是的,但我遇到的问题是关于 SAVE 上的错误映射。我会添加到我的 q 中。
    猜你喜欢
    • 2021-01-30
    • 2010-11-28
    • 2011-05-02
    • 1970-01-01
    • 1970-01-01
    • 2014-04-28
    • 2017-10-12
    • 1970-01-01
    • 2022-07-12
    相关资源
    最近更新 更多