Spring测试中Hiberante session缓存问题

测试很关键..没有测试的代码是遗留代码...

Spring给测试提供了好多方便之处.

引用

使用Junit直接进行单元测试有以下四大不足:

  1)导致多次Spring容器初始化问题

  根据JUnit测试方法的调用流程,每执行一个测试方法都会创建一个测试用例的实例并调用setUp()方法。由于一般情况下,我们在setUp()方法中初始化Spring容器,这意味着如果测试用例有多少个测试方法,Spring容器就会被重复初始化多次。虽然初始化Spring容器的速度并不会太慢,但由于可能会在Spring容器初始化时执行加载Hibernate映射文件等耗时的操作,如果每执行一个测试方法都必须重复初始化Spring容器,则对测试性能的影响是不容忽视的;

  -->使用Spring测试套件,Spring容器只会初始化一次!

  2)需要使用硬编码方式手工获取Bean

  在测试用例类中我们需要通过ctx.getBean()方法从Spirng容器中获取需要测试的目标Bean,并且还要进行强制类型转换的造型操作。这种乏味的操作迷漫在测试用例的代码中,让人觉得烦琐不堪;

  -->使用Spring测试套件,测试用例类中的属性会被自动填充Spring容器的对应Bean ,无须在手工设置Bean!

  3)数据库现场容易遭受破坏

  测试方法对数据库的更改操作会持久化到数据库中。虽然是针对开发数据库进行操作,但如果数据操作的影响是持久的,可能会影响到后面的测试行为。举个例子,用户在测试方法中插入一条ID为1的User记录,第一次运行不会有问题,第二次运行时,就会因为主键冲突而导致测试用例失败。所以应该既能够完成功能逻辑检查,又能够在测试完成后恢复现场,不会留下“后遗症”;

  -->使用Spring测试套件,Spring会在你验证后,自动回滚对数据库的操作,保证数据库的现场不被破坏,因此重复测试不会发生问题!

  4)不方便对数据操作正确性进行检查

  假如我们向登录日志表插入了一条成功登录日志,可是我们却没有对t_login_log表中是否确实添加了一条记录进行检查。一般情况下,我们可能是打开数据库,肉眼观察是否插入了相应的记录,但这严重违背了自动测试的原则。试想在测试包括成千上万个数据操作行为的程序时,如何用肉眼进行检查?

  -->只要你继承Spring的测试套件的用例类,你就可以通过jdbcTemplate在同一事务中访问数据库,查询数据的变化,验证操作的正确性!


在用spring做测试的时候,会选择强大的AbstractTransactionalDataSourceSpringContextTests类.

但从过去的帖子里都会看到的问题身影
http://www.iteye.com/article/40451
http://www.iteye.com/topic/70008

最近在使用spring测试的时候也出现了类似的问题.
这个问题不同于以上两个帖子.
结果是一样的,测试不通过..
但不是数据库没有执行.
因为在使用setComplete()方法之后,数据库中的数据都成功完成.说明不是事务问题.
但在查询的时候依然是上一次查询的数据..
这就是一级缓存在作怪.

引用

Remember that you can clear the Hibernate session, removing objects already associated with it. This is often necessary before requerying in tests, and solves most (if not all) problems.
I typically use JDBC for verification. The pattern is
- do Hibernate operation
- flush Hibernate session
- issue JDBC query to verify results

That way I'm verifying what Hibernate did to the database in the same transaction.
__________________
Rod Johnson - CEO, Interface21
http://www.springframework.com - Spring From the Source
Training, Consulting, Support


使用flush方法是使数据库操作.flush是把数据与数据库同步...
要清除缓存中的数据要使用evict或者clear方法.
但总不能为了测试,在DAO中查询后清下缓存吧..那太不合理了.

http://www.iteye.com/topic/18826
这个帖子里给出了解决之道
在测试超类中写上
protected void flushSession();{   
        SessionFactory sessionFactory =    
            (SessionFactory)applicationContext.getBean("sessionFactory");  
        sessionFactory.getCurrentSession().flush();
sessionFactory.getCurrentSession().clear();      
    }  


在测试方法中,如果要查询已查询过的数据,可以在查询之前用调用下这个方法..

你可能感兴趣的:(spring,Hibernate,bean,单元测试,JUnit)