您的位置:首页 > 编程语言 > Java开发

关于在 Spring 中对 DAO 进行单元测试的一些问题

2006-12-16 21:45 393 查看
@page { size: 20.999cm 29.699cm; margin-top: 2cm; margin-bottom: 2cm; margin-left: 2cm; margin-right: 2cm }
table { border-collapse:collapse; border-spacing:0; empty-cells:show }
td, th { vertical-align:top; }
h1, h2, h3, h4, h5, h6 { clear:both }
ol, ul { padding:0; }
* { margin:0; }
*.Caption { font-family:'Bitstream Vera Serif'; font-size:12pt; margin-top:0.212cm; margin-bottom:0.212cm; font-style:italic; }
*.Heading { font-family:'Bitstream Vera Serif'; font-size:14pt; margin-top:0.423cm; margin-bottom:0.212cm; }
*.Index { font-family:'Bitstream Vera Serif'; font-size:12pt; }
*.List { font-family:'Bitstream Vera Serif'; font-size:12pt; margin-top:0cm; margin-bottom:0.212cm; }
*.P1 { font-family:'Bitstream Vera Serif'; font-size:10.5pt; }
*.P10 { font-family:'Courier 10 Pitch'; font-size:10pt; margin-left:0cm; margin-right:0cm; text-align:left ! important; text-indent:0cm; color:#646464; }
*.P11 { font-family:'Courier 10 Pitch'; font-size:10.5pt; margin-left:0cm; margin-right:0cm; text-align:left ! important; text-indent:0cm; }
*.P12 { font-family:'Bitstream Vera Serif'; font-size:10.5pt; margin-left:0cm; margin-right:0cm; text-align:left ! important; text-indent:0cm; }
*.P13 { font-family:'Courier 10 Pitch'; font-size:10.5pt; }
*.P2 { font-family:'Bitstream Vera Serif'; font-size:10.5pt; }
*.P3 { font-family:'Bitstream Vera Serif'; font-size:12pt; }
*.P4 { font-family:'Courier 10 Pitch'; font-size:10pt; }
*.P5 { font-family:'Courier 10 Pitch'; font-size:10pt; margin-left:0cm; margin-right:0cm; text-align:left ! important; text-indent:0cm; }
*.P6 { font-family:'Courier 10 Pitch'; font-size:10pt; margin-left:0cm; margin-right:0cm; text-align:left ! important; text-indent:0cm; color:#000000; }
*.P7 { font-family:'Courier 10 Pitch'; font-size:12pt; margin-left:0cm; margin-right:0cm; text-align:left ! important; text-indent:0cm; }
*.P8 { font-family:'Courier 10 Pitch'; font-size:12pt; }
*.P9 { font-family:'Courier 10 Pitch'; font-size:12pt; margin-left:0cm; margin-right:0cm; text-align:left ! important; text-indent:0cm; }
*.Standard { font-family:'Bitstream Vera Serif'; font-size:12pt; }
*.Textbody { font-family:'Bitstream Vera Serif'; font-size:12pt; margin-top:0cm; margin-bottom:0.212cm; }
*.Internetlink { color:#000080; text-decoration:underline; }
*.StrongEmphasis { font-weight:bold; }
*.T1 { font-family:'Bitstream Vera Serif'; }
*.T10 { color:#000000; font-size:10pt; }
*.T11 { color:#646464; }
*.T12 { color:#3f5fbf; }
*.T13 { font-family:'Courier 10 Pitch'; }
*.T14 { color:#000000; font-weight:bold; }
*.T15 { color:#000000; font-family:'Courier 10 Pitch'; }
*.T16 { font-family:'Courier 10 Pitch'; font-size:10.5pt; }
*.T17 { font-size:10.5pt; }
*.T18 { font-size:10.5pt; }
*.T2 { color:#7f0055; font-weight:bold; }
*.T3 { color:#161616; }
*.T4 { color:#000000; }
*.T5 { color:#0000c0; }
*.T6 { color:#2a00ff; }
*.T7 { color:#0000c0; font-style:italic; }
*.T8 { color:#000000; font-style:italic; }
*.T9 { color:#000000; font-size:10pt; }

最近在使用 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 之类的支持事务管理的存储引擎,否则一定会出现各种奇怪的逻辑错误。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: