本站首页    管理页面    写新日志    退出


«December 2025»
123456
78910111213
14151617181920
21222324252627
28293031


公告
 本博客在此声明所有文章均为转摘,只做资料收集使用。

我的分类(专题)

日志更新

最新评论

留言板

链接

Blog信息
blog名称:
日志总数:1304
评论数量:2242
留言数量:5
访问次数:7666661
建立时间:2006年5月29日




[Spring]关于在 Spring 中对 DAO 进行单元测试的一些问题
软件技术

lhwork 发表于 2006/12/21 8:46:43

最近在使用 Spring 2.0 和 Hibernate 3.2.0 进行开发,在对 DAO 进行单元测试的时候,出现了一些问题,因为对新环境不太熟悉,折腾了很久才把问题略为妥善的解决。 程序员喜欢用代码说话,所以先将测试的相关代码展示如下: public class FilterSetDaoTest extends TestCase {    private FilterSetDao filterSetDao;     public void testCreateFilterSet() {       FilterSet filterSet = new FilterSet();       filterSet.setName("test10");       filterSet.setCreateTime(new Date());        Set<Filter> filters = new HashSet<Filter>();       Filter filter = new Filter();       filter.setRule("testrule10");       filter.setType(FilterType.PLAIN);       filter.setCreateTime(new Date());       filters.add(filter);       filterSet.setFilters(filters);       filterSet.setUpdateTime(new Date());        filterSetDao.saveOrUpdate(filterSet);        FilterSet persistedFilterSet = filterSetDao.find(filterSet.getId());       assertEquals(filterSet, persistedFilterSet);       assertEquals(1, persistedFilterSet.getFilters().size());    }} public interface FilterSetDao {    public FilterSet find(int id);} public class FilterSetDaoHibernateImpl extends HibernateDaoSupport implements FilterSetDao {    public FilterSet find(int id) {       return (FilterSet) getHibernateTemplate().load(FilterSet.class,  id);    }} @Entity @Table(name = "filterset")public class FilterSet implements Serializable {    private Set<Filter> filters;    @ManyToMany(cascade = CascadeType.ALL)    public Set<Filter> getFilters() {       return filters;    }} 因为在 Hibernate 中,Session.load() 方法返回的是实体类的一个代理类的实例,而此时因为没有合适的事务处理代码,相应的 session 已经关闭,所以在执行第一条 assertEquals() 方法时,即报告“LazyInitializationException: could not initialize proxy-the owning Session was closed”异常。可以将 DAO 实现中的 load() 换成 get()。return (FilterSet) getHibernateTemplate().get(FilterSet.class, id);因为 get() 是返回的不是代理类的实例,而直接返回实体类的实例,所以上面的异常将不会出现。但是 FilterSet 中的 filters 属性为 Set 类型,而在 Hibernate 3 中,默认对所有 Collection 和 Map 都采用 lazy initialization 的方式,因此在这里,基于上面所说的原因,又会报告“org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: net.patrickhe.FilterSet.filters, no session or session was closed” 这样的错误。所以,将 load() 换成 get() 其实并不是良好的解决办法。按照 Spring Reference 上的说明,如果想在事务支持的环境下进行单元测试,可以让自己的测试用例类继承 org.springframework.test.annotation.AbstractAnnotationAwareTransactionalTests,如此即可。AbstractAnnotationAwareTransactionalTests 默认会关闭自动提交的特性,在测试方法执行完毕之后即进行回滚操作,以便清除方才测试时对数据库造成的修改变更。如果需要将测试数据提交到数据库中的话,那也很容易,直接调用 继承而来的 setComplete() 方法即可。关于 AbstractAnnotationAwareTransactionalTests 的更加详尽说明可以参考 Spring Reference - 8.3.3 Transaction management 一节。 注:在需要事务支持的环境中进行开发,如果使用 MySQL 作为持久化介质,一定要采用 InnoDB 之类的支持事务管理的存储引擎,否则一定会出现各种奇怪的逻辑错误。


阅读全文(3735) | 回复(0) | 编辑 | 精华
 



发表评论:
昵称:
密码:
主页:
标题:
验证码:  (不区分大小写,请仔细填写,输错需重写评论内容!)



站点首页 | 联系我们 | 博客注册 | 博客登陆

Sponsored By W3CHINA
W3CHINA Blog 0.8 Processed in 1.109 second(s), page refreshed 144798721 times.
《全国人大常委会关于维护互联网安全的决定》  《计算机信息网络国际联网安全保护管理办法》
苏ICP备05006046号