envers
Envers是一个Hibernate模块,可以将其配置为自动审核对您的实体所做的更改。 因此,每个审核的实体都与修订列表相关联,每个修订都在发生更改时捕获实体的状态。 但是,在我对DAO进行“单元测试”时遇到了一个障碍,这就是我要分享的内容,以避免其他人陷入同一困境。
首先,让我们概述使用Envers所需的几个步骤:
@Audited
注释为您的实体注释:
@Entity
@Audited
publicclassPerson{
// Properties
}
SessionFactory
注册Envers AuditEventListener
:
<beanid="sessionFactory"class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<propertyname="dataSource"ref="dataSource"/>
<propertyname="packagesToScan"value="ch.frankel.blog.envers.entity"/>
<propertyname="hibernateProperties">
<props>
<propkey="hibernate.dialect"> org.hibernate.dialect.H2Dialect </prop>
</props>
</property>
<propertyname="schemaUpdate"value="true"/>
<propertyname="eventListeners">
<map>
<entrykey="post-insert"value-ref="auditListener"/>
<entrykey="post-update"value-ref="auditListener"/>
<entrykey="post-delete"value-ref="auditListener"/>
<entrykey="pre-collection-update"value-ref="auditListener"/>
<entrykey="pre-collection-remove"value-ref="auditListener"/>
<entrykey="post-collection-recreate"value-ref="auditListener"/>
</map>
</property>
</bean>
<beanid="auditListener"class="org.hibernate.envers.event.AuditEventListener"/>
DataSourceTransactionManager
):
<beanid="transactionManager"class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<propertyname="sessionFactory"ref="sessionFactory"/>
</bean>
@ContextConfiguration("classpath:spring-persistence.xml")
@TransactionConfiguration(defaultRollback=false)
publicclassPersonDaoImplTestextendsAbstractTransactionalTestNGSpringContextTests{
@Autowired
privatePersonDaopersonDao;
@BeforeMethod
protectedvoidsetUp(){
// Populate database
}
@Test
publicvoidpersonShouldBeAudited(){
Personperson=personDao.get(1L);
person.setFirstName("Jane");
List<Person>history=personDao.getPersonHistory(1L);
assertNotNull(history);
assertFalse(history.isEmpty());
assertEquals(history.size(),1);
}
}
奇怪的是,当您执行上一个测试类时,如果检查列表不为空,则测试方法将失败:是,这意味着没有与该实体相关联的修订。 Morevoer,日志中什么也没有显示。 但是, 修订在测试结束时显示在审核表中(前提是您没有在执行表后清除表)。
出现了一个可怕的问题:为什么? 好吧,似乎仅在提交事务时才调用Hibernate事件后监听器。 在我们的例子中,它匹配:方法完成后,事务由Spring提交,我们的测试树在方法内部进行断言。
为了使测试通过,我们必须在方法内部手动管理事务,以将更新提交到数据库。
@Test
publicvoidpersonShouldBeAuditedWhenUpdatedWithManualTransaction(){
PlatformTransactionManagertxMgr=applicationContext.getBean(PlatformTransactionManager.class);
// A new transaction is required, the wrapping transaction is for Envers
TransactionStatusstatus=txMgr.getTransaction(newDefaultTransactionDefinition(PROPAGATION_REQUIRES_NEW));
Personperson=personDao.get(1L);
person.setFirstName("Jane");
txMgr.commit(status);
List<Person>history=personDao.getPersonHistory(1L);
assertNotNull(history);
assertFalse(history.isEmpty());
assertEquals(history.size(),1);
}
一方面,测试通过,并且日志相应地显示了SQL命令。 另一方面,成本是使它通过所需的额外样板代码。
当然,可以(应该?)首先质疑是否需要测试该功能。 由于它是库带来的功能,其背后的原因可能是,如果您不信任该库,则根本不要使用它。 就我而言,这是我第一次使用Envers,因此不可否认,我必须在我和图书馆之间建立信任。 但是,即使使用受信任的库,我也会测试特定的情况:例如,当使用Hibernate时,我会创建测试类以验证复杂的查询是否能为我提供正确的结果。 因此,审核被视为一个复杂的用例,我想尽快意识到其不良行为。
您可以在此处以Maven / Eclipse格式找到本文的资源。
翻译自: https://blog.frankel.ch/how-to-test-code-that-uses-envers/
envers