spring DAO集成测试的方法
在进行dao的集成测试时候,数据清理,察看数据都是比较麻烦的事情,使用Spring-mock.jar可以帮助我们简化着一个过程。我举一个简单的例子,说明一下如何使用spring-mock。
首先是po, hbm.xml, dao, daoimpl没什么好说的:
- Customer.java:
- packagerst.spring.mock;
- importjava.io.Serializable;
- /**@authorHibernateCodeGenerator*/
- publicclassCustomerimplementsSerializable{
- /**identifierfield*/
- privateLongid;
- /**nullablepersistentfield*/
- privateStringname;
- /**fullconstructor*/
- publicCustomer(Stringname){
- this.name=name;
- }
- /**defaultconstructor*/
- publicCustomer(){
- }
- publicLonggetId(){
- returnthis.id;
- }
- publicvoidsetId(Longid){
- this.id=id;
- }
- publicStringgetName(){
- returnthis.name;
- }
- publicvoidsetName(Stringname){
- this.name=name;
- }
- }
- Customer.hbm.xml:
- <?xmlversion="1.0"encoding="UTF-8"?>
- <!DOCTYPEhibernate-mappingPUBLIC
- "-//Hibernate/HibernateMappingDTD//EN"
- "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
- <hibernate-mappingpackage="rst.spring.mock">
- <classname="Customer"table="customer">
- <idname="id"column="id"type="long"unsaved-value="null">
- <generatorclass="identity"/>
- </id>
- <propertyname="name"column="name"type="string"/>
- </class>
- </hibernate-mapping>
- CustomerDAO:
- /*
- *Createdon2005-3-25
- */
- packagerst.spring.mock;
- importorg.springframework.dao.DataAccessException;
- /**
- *@authorrst
- *
- */
- publicinterfaceCustomerDAO{
- publicvoidadd(Customercustomer)throwsDataAccessException;
- }
- CustomerDAOImpl:
- packagerst.spring.mock;
- importorg.springframework.dao.DataAccessException;
- importorg.springframework.orm.hibernate.support.HibernateDaoSupport;
- /**
- *Classdescription.
- *
- *@authorrst
- */
- publicclassCustomerDAOHibernateImplextendsHibernateDaoSupportimplementsCustomerDAO{
- publicvoidadd(Customercustomer)throwsDataAccessException{
- this.getHibernateTemplate().save(customer);
- }
- }
然后测试的基类SpringDAOTestCase继承自AbstractTransactionalDataSourceSpringContextTests,目前只有一个指定测试用xml文件位置的逻辑。
- packagerst.spring.mock;
- importorg.springframework.test.AbstractTransactionalDataSourceSpringContextTests;
- /**
- *Classdescription.
- *
- *@authorrst
- */
- publicabstractclassSpringDAOTestCaseextendsAbstractTransactionalDataSourceSpringContextTests{
- protectedString[]getConfigLocations(){
- returnnewString[]{"test.xml"};
- }
- }
接着是我们真正测试的类CustomerDAOTest.java:
- packagerst.spring.mock;
- /**
- *Classdescription.
- *
- *@authorrst
- */
- publicclassCustomerDaoTestextendsSpringDAOTestCase{
- privateCustomerDAOHibernateImplcustomerDAO;
- protectedvoidonSetUpInTransaction()throwsException{
- super.onSetUpInTransaction();
- //this.setPopulateProtectedVariables(true);
- customerDAO=(CustomerDAOHibernateImpl)this.applicationContext.getBean("customerDAO");
- }
- protectedvoidonTearDownInTransaction(){
- customerDAO=null;
- }
- publicvoidtestInsert(){
- Customercustomer=newCustomer();
- customer.setName("javaeye");
- customerDAO.add(customer);
- Stringname=(String)jdbcTemplate.queryForObject("selectnamefromcustomerwhereid=?",newObject[]{customer.getId()},String.class);
- assertEquals(customer.getName(),name);
- }
- }
最后看看配置文件test.xml:
- <?xmlversion="1.0"encoding="UTF-8"?>
- <!DOCTYPEbeansPUBLIC"-//SPRING//DTDBEAN//EN""http://www.springframework.org/dtd/spring-beans.dtd">
- <!--
- -ApplicationcontextdefinitionforPetcliniconHibernate.
- -->
- <beans>
- <!--=========================RESOURCEDEFINITIONS=========================-->
- <!--Configurerthatreplaces${...}placeholderswithvaluesfromapropertiesfile-->
- <!--(inthiscase,JDBC-relatedsettingsforthedataSourcedefinitionbelow)-->
- <beanid="propertyConfigurer"class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
- <propertyname="location"><value>classpath:jdbc.properties</value></property>
- </bean>
- <!--LocalDataSourcethatworksinanyenvironment-->
- <beanid="dataSource"class="org.springframework.jdbc.datasource.DriverManagerDataSource">
- <propertyname="driverClassName"><value>${jdbc.driverClassName}</value></property>
- <propertyname="url"><value>${jdbc.url}</value></property>
- <propertyname="username"><value>${jdbc.username}</value></property>
- <propertyname="password"><value>${jdbc.password}</value></property>
- </bean>
- <!--HibernateSessionFactory-->
- <beanid="sessionFactory"class="org.springframework.orm.hibernate.LocalSessionFactoryBean">
- <propertyname="dataSource"><reflocal="dataSource"/></property>
- <propertyname="mappingResources">
- <value>rst/spring/mock/Customer.hbm.xml</value>
- </property>
- <propertyname="hibernateProperties">
- <props>
- <propkey="hibernate.dialect">${hibernate.dialect}</prop>
- <propkey="hibernate.show_sql">true</prop>
- </props>
- </property>
- </bean>
- <!--TransactionmanagerforasingleHibernateSessionFactory(alternativetoJTA)-->
- <beanid="transactionManager"class="org.springframework.orm.hibernate.HibernateTransactionManager">
- <propertyname="sessionFactory"><reflocal="sessionFactory"/></property>
- </bean>
- <beanid="hibernateTemplate"class="org.springframework.orm.hibernate.HibernateTemplate">
- <propertyname="sessionFactory"><reflocal="sessionFactory"/></property>
- </bean>
- <beanid="customerDAO"class="rst.spring.mock.CustomerDAOHibernateImpl">
- <propertyname="hibernateTemplate"><reflocal="hibernateTemplate"/></property>
- </bean>
- </beans>
这个文件很简单,不要忘记transactionManager的配置,Test类会自动装配的。
运行之后,就可以看到应有的结果,并且数据库中不会有数据污染。这个过程主要是开始一个transaction,然后开始你的test方法,执行dao操作,执行sql查询验证结果,最后无论成功失败rollback transaction。
也许我孤陋寡闻,我是最近才发现的。
1.Spring Mock。
Mock主要用于测试Controller(or Action),Controller等同于一个Servlet,要测试它里面的方法,必须至少传入HttpRequest和HttpResponse
两个类的实例作为参数参数,直接new 一个HttpRequest是豪无意义的,必须使用mock。
Spring的mock那个包就提供了HttpRequest、HttpResponse、HttpSession的mock,测试controller时就可以直接new一个对象!
完整的测试代码Demo如下:
- packageorg.ggyy.web.test;
- importjunit.framework.TestCase;
- importjava.io.File;
- importjava.io.IOException;
- importjava.util.List;
- importjava.util.Map;
- importjavax.servlet.http.HttpServletRequest;
- importjavax.servlet.http.HttpServletResponse;
- importjunit.framework.TestCase;
- importorg.apache.commons.logging.Log;
- importorg.apache.commons.logging.LogFactory;
- importorg.ggyy.bo.Cat;
- importorg.ggyy.web.ctrl.CatController;
- importorg.springframework.mock.web.MockHttpServletRequest;
- importorg.springframework.mock.web.MockHttpServletResponse;
- importorg.springframework.mock.web.MockServletContext;
- importorg.springframework.web.context.support.XmlWebApplicationContext;
- importorg.springframework.web.servlet.ModelAndView;
- publicclassListCatTestextendsTestCase{
- privatestaticLoglog=LogFactory.getLog(ListCatTest.class);
- privateXmlWebApplicationContextctx;
- publicvoidsetUp(){
- String[]paths={
- "file:/d:/eclipse/workspace/cat/WebRoot/WEB-INF/applicationContext.xml",
- "file:/d:/eclipse/workspace/cat/WebRoot/WEB-INF/pet-servlet.xml"};
- ctx=newXmlWebApplicationContext();
- ctx.setConfigLocations(paths);
- ctx.setServletContext(newMockServletContext(""));
- ctx.refresh();
- }
- publicvoidtestGetUsers()throwsException{
- MockHttpServletRequestrequest=newMockHttpServletRequest();
- MockHttpServletResponseresponse=newMockHttpServletResponse();
- request.addParameter("parentId","2");
- CatControllerc=(CatController)ctx.getBean("catController");
- ModelAndViewmav=c.listCatHandler(request,response);
- Mapm=mav.getModel();
- }
- }
catController是MultiActionController,listCatHandler是其中的一个action。这里使用了绝对路径: "file:/d:/eclipse/workspace/cat/WebRoot/WEB-INF/pet-servlet.xml"。相对路径好像调试不出来。
2.基于Spring容器管理事务的测试--可以我表述不是很准确^_^
对于service层和dao的测试一般都是在实际的数据库中进行测试的,假如你不想使得测试对原来数据库造成任何影响,可以使用这种测试策略。整个测试是在Spring管理的事务中进行的,测试完毕,可以选择提交事务,也可以不提交事务,也就是说测试完后对原来的数据库的记录不造成任何影响。
这种测试策略最为诱人的还是:当测试不通过,也就是抛出异常时,事务可以自动回滚的!我以前测试前要清空数据库,测试不通过时测试用例后面的delete方法不能运行,我不得不手工的删除这些数据。
对于测试用例所依赖的bean,声明该bean的一个setter方法spring就可以自动的注入一个实例--很有意思,和ejb3.0类似。
我从pdf文档考下来一个demo供大家观赏:
- publicabstractclassAbstractClinicTestsextendsAbstractTransactionalDataSourceSpringContextTests{
- protectedClinicclinic;
- publicvoidsetClinic(Clinicclinic){
- this.clinic=clinic;
- }
- publicvoidtestGetVets(){
- Collectionvets=this.clinic.getVets();
- assertEquals("JDBCquerymustshowthesamenumberofvets",
- jdbcTemplate.queryForInt("SELECTCOUNT(0)FROMVETS"),
- vets.size());
- Vetv1=(Vet)EntityUtils.getById(vets,Vet.class,2);
- assertEquals("Leary",v1.getLastName());
- assertEquals(1,v1.getNrOfSpecialties());
- assertEquals("radiology",((Specialty)v1.getSpecialties().get(0)).getName());
- Vetv2=(Vet)EntityUtils.getById(vets,Vet.class,3);
- assertEquals("Douglas",v2.getLastName());
- assertEquals(2,v2.getNrOfSpecialties());
- assertEquals("dentistry",((Specialty)v2.getSpecialties().get(0)).getName());
- assertEquals("surgery",((Specialty)v2.getSpecialties().get(1)).getName());
- }
上面的clinic实例是自动注入的,
本文地址:http://www.45fan.com/dnjc/69991.html