ricelane 2006-10-20 17:52
spring+hibernate单元测试(转)
这两天的花费了一些时间在使用spring-mock进行spring的单元测试问题上,基本上对这个问题有了一个完整的解决方案
下面将对相关学习到和思考到的一些问题进行一下整理:
1、首先明确一下问题:要对什么进行单元测试?
我的问题是围绕这一个DAO展开,我定义了一个DAO接口XXXDAO,并且写了该DAO的实现XXXDAOImpl,然后使用spring对接口的实现进行管理:
<bean id="XXXDAO" class="com.easou.datastat.base.dao.impl.XXXDAOImpl">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
<property name="hibernateTemplate">
<ref bean="hibernateTemplate"/>
</property>
</bean>
现在问题开始明确了,我要对XXXDAOImpl进行单元测试。这里需要指明一个问题就是单元测试,测试的是有实现代码的实现类,而不是接口。
2、接着是下一个问题,如何取得Sping的上下文关系呢?
这里就需要用到spring-mock了,其中有一个测试基类是AbstractTransactionalDataSourceSpringContextTests
我让测试用例XXXDAOImplTestcase继承AbstractTransactionalDataSourceSpringContextTests,然后override其中的方法getConfigLocations()
具体代码如下:
public class XXXDAOImplTestCase extends AbstractTransactionalDataSourceSpringContextTests {
@Override
protected String[] getConfigLocations() {
// TODO get the spring context
String[] config = new String[]{"file:D:\\javawork\\workspace\\datastat\\docroot\\WEB-INF\\applicationContext.xml","file:D:\\javawork\\workspace\\datastat\\docroot\\WEB-INF\\applicationContext-base.xml"};
return config;
}
}
不难看出,该方法是为了读入spring的上下文信息,这样的话这个测试用例就可以直接使用spirng中定义的bean了
但是这里需要注意一个问题*,就是文件路径的问题,这里为了能够清楚地说明文件的路径规则我引用了spring-mock官方的getConfigLocation方法说明
Subclasses must implement this method to return the locations of their config files. A plain path will be treated as class path location. E.g.: "org/springframework/whatever/foo.xml". Note however that you may prefix path locations with standard Spring resource prefixes. Therefore, a config location path prefixed with "classpath:" with behave the same as a plain path, but a config location such as "file:/some/path/path/location/appContext.xml" will be treated as a filesystem location.
3 好了,该到最后一个问题了,取得Spirng上下问中定义的bean的实例来进行单元测试
这里有两种方法,一种是定义一个代测单元的对象,然后定义好get,set方法,AbstractTransactionalDataSourceSpringContextTests会自动根据Spring的上下文得到待测单元的具体实现。
private ExQueryDAO exQqueryDAO;
/** *//**
* @return 返回 exQqueryDAO。
*/
public ExQueryDAO getExQqueryDAO() {
return exQqueryDAO;
}
/** *//**
* @param exQqueryDAO 要设置的 exQqueryDAO。
*/
public void setExQqueryDAO(ExQueryDAO exQqueryDAO) {
this.exQqueryDAO = exQqueryDAO;
}
另外一种就是使用applicationContext.getBean("XXXDAO");的方法取得实例
XXXDAO xxxDAO = (XXXDAO)applicationContext.getBean("XXXDAO");
接下来你就可以用这个bean的具体实现对相关方法进行unittest了
这里补充一个问题就是单元测试的运行环境问题*,由于你可能在spring的配置文件中指定一些外部类所以你必须在junit的运行环境中指定使用到的classpath,下面是eclipse的junit配置classpath
最后我对整体的spring+hibernate的jsf框架进行了一下单元测试的框架总结,主要多了一个基本的BaseTestCase,用于统一读取applicationContext
可以看到下面的pagebean和jsp页面以及相关的taglib的单元测试我还没有完成:),我将在今后几天继续研究相关的单元测试问题
Jimmyshao 2006-10-21 16:59
人气太少了。顶。。
walker1020 2006-10-24 13:22
这么好的文章为什么没有人来顶呢? 奇怪?!
wing821022 2007-6-5 22:48
up
tiangou99073 2007-7-26 19:20
不错
tangjinglh 2007-9-11 11:34
感觉很好,可是没有开发经验,只做过黑盒,看不懂!sdlkfj7
正道 2007-11-7 14:28
Spring Framework 开发参考手册中说:
“单元测试
采用依赖注射的一个主要好处是你的代码对容器的依赖将比传统J2EE开发小的多。无需Spring或任何其他容器,只要简单地通过 new 操作符即可实例化对象,通过这种方式组成你应用的POJO对象就可以充分利用JUnit进行测试了。你可以使用模拟对象或者其他很多有价值的测试技术将你的代码隔离起来进行测试。如果你的应用在架构上遵循了Spring的建议,那么你的代码将会有清晰的层次和高度的模块化,这些都将大大方便单元测试。例如,在单元测试中你可以通过测试框架或者模拟DAO接口的方式来测试服务层对象而无需访问持久化数据。
真正的单元测试运行起来通常都非常迅速,因为没有应用服务器,数据库,ORM工具等运行设施需要设置。因此加强正确的单元测试可以大大提高你的生产力。所以并不需要本节来帮助你为你那些基于IoC的应用编写有效的 单元 测试。
”
Copies of this document may be made for your own use and for distribution to others, provided that you do not charge any fee for such copies and further provided that each copy contains this Copyright Notice, whether distributed in print or electronically.
hellen_ma 2007-11-19 11:08
i can't understand it.
up