当前位置: 首页 > 工具软件 > Envers > 使用案例 >

envers_如何测试使用Envers的代码

皮弘博
2023-12-01

envers

Envers是一个Hibernate模块,可以将其配置为自动审核对您的实体所做的更改。 因此,每个审核的实体都与修订列表相关联,每个修订都在发生更改时捕获实体的状态。 但是,在我对DAO进行“单元测试”时遇到了一个障碍,这就是我要分享的内容,以避免其他人陷入同一困境。

首先,让我们概述使用Envers所需的几个步骤:

  • @Audited注释为您的实体注释:
    @Entity
    @Audited
    publicclassPerson{
        // Properties
    }
  • 通过Spring在您的Hibernate 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"/>
  • 将Hibernate事务管理器配置为您的事务管理器。 请注意,如果您使用其他事务管理器,则不会触发审核(想到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

 类似资料: