单元测试在标记为@Transactional时传递,但在没有时则失败

时间:2012-03-26 18:40:32

标签: java spring hibernate jpa junit

设置JUNIT测试

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

 @Test
 public void testMappingsOfHugeObjectGraph(){
 }
}

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

如果我把@Transactional带走,我的某些关系就会出错,这是我所期待的。任何人都会想到为什么它没有失败@Transactional

编辑:要澄清,抛出的异常是关于糟糕的hibernate映射(它是一个非常大的对象结构,并且我已经将其中的一部分borked)保存对象

2 个答案:

答案 0 :(得分:5)

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

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

解决方案是将@Transactional放在其位置并注入

@PersistenceContext
private EntityManager em;

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

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

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

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

希望它有所帮助。

答案 1 :(得分:0)

如果你带走@Transactional,Hibernate工厂就会以相当于自动提交模式的方式运行,你所做的每个新访问都会产生一个全新的Session。因此,一旦您检索到对象,它就会立即不再与打开的会话相关联,并且不符合延迟加载的条件。