在Spring JUnit测试中没有调用Hibernate监听器

时间:2014-12-07 15:21:30

标签: java spring hibernate unit-testing junit

我用Hibernate作为数据访问层创建Spring MVC应用程序。我的所有实体都包含createdOnupdatedOn字段,其中包含创建/更新实体时的时间戳。 createdOn字段使用PreInsertEventListener设置,updatedOn字段使用PreUpdateEventListener设置。

当我运行我的应用程序时,它按预期工作,监听器被注册,当我保存实体时,调用适当的侦听器(使用调试器验证)。但是当我尝试对这种行为进行单元测试时,监听器已经注册,但从未被调用过。

我决定使用调试,当我在我的应用程序EntityInsertAction#preInsert中保存一个实体时,它会循环注册的侦听器并调用它们。但是当我运行单元测试时,从不调用此方法。

以下是我的单元测试示例:

@ActiveProfiles("test")
@Transactional
@TransactionConfiguration
@ContextConfiguration(classes = {
        BaseConfiguration.class,
        DatabaseConfiguration.class
})
@RunWith(SpringJUnit4ClassRunner.class)
public class HibernateListenerTest {

    @Autowired
    private FooDao fooDao;

    @Test
    public void testPreUpdateListener() {
        Foo foo = fooDao.merge(createFoo());
        Assert.assertNotNull(foo.getCreatedOn());
        Assert.assertNull(foo.getUpdatedOn());

        foo.setBar("Bar");
        foo = fooDao.merge(foo);
        Assert.assertNotNull(foo.getUpdatedOn());
    }

}

由于未调用侦听器,因此单元测试始终失败,但出现以下异常:

org.hibernate.PropertyValueException: not-null property references a null or transient value

所以我的问题是:为什么在运行应用程序和运行单元测试之间这种行为有所不同,以及是否有办法修复代码以便在单元测试中正确调用侦听器?

提前感谢任何输入。如果需要其他代码/信息,请发表评论。

1 个答案:

答案 0 :(得分:4)

如果您正在测试Hibernate侦听器,请在断言之前手动调用Session#flush

让Spring将SessionFactory注入您的测试并执行sessionFactory.getCurrentSession().flush();

如果您希望您的听众在刷新会话之前采取行动,那么您需要使用不同的事件(例如MERGE或PERSIST)。