spring DAO 集成测试 实例

在进行dao的集成测试时候,数据清理,察看数据都是比较麻烦的事情,使用Spring-mock.jar可以帮助我们简化着一个过程。我举一个简单的例子,说明一下如何使用spring-mock。

首先是po, hbm.xml, dao, daoimpl没什么好说的:

代码
  1. Customer.java :    
  2.   
  3. package rst.spring.mock;   
  4.   
  5. import java.io.Serializable;   
  6.   
  7. /** @author Hibernate CodeGenerator */   
  8. public class Customer implements Serializable {   
  9.   
  10.     /** identifier field */   
  11.     private Long id;   
  12.   
  13.     /** nullable persistent field */   
  14.     private String name;   
  15.   
  16.     /** full constructor */   
  17.     public Customer(String name) {   
  18.         this.name = name;   
  19.     }   
  20.   
  21.     /** default constructor */   
  22.     public Customer() {   
  23.     }   
  24.   
  25.     public Long getId() {   
  26.         return this.id;   
  27.     }   
  28.   
  29.     public void setId(Long id) {   
  30.         this.id = id;   
  31.     }   
  32.   
  33.     public String getName() {   
  34.         return this.name;   
  35.     }   
  36.   
  37.     public void setName(String name) {   
  38.         this.name = name;   
  39.     }   
  40.   
  41. }   
  42.   
  43. Customer.hbm.xml :   
  44.   
  45. <?xml version="1.0" encoding="UTF-8"?>  
  46. <!DOCTYPE hibernate-mapping PUBLIC   
  47.         "-//Hibernate/Hibernate Mapping DTD//EN"   
  48.         "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">  
  49. <hibernate-mapping package="rst.spring.mock">  
  50.     <class name="Customer" table="customer">  
  51.         <id name="id" column="id" type="long" unsaved-value="null">  
  52.             <generator class="identity"/>  
  53.         </id>  
  54.         <property name="name" column="name" type="string"/>  
  55.     </class>  
  56.   
  57. </hibernate-mapping>  
  58.   
  59. CustomerDAO :   
  60. /*   
  61.  * Created on 2005-3-25   
  62.  */   
  63. package rst.spring.mock;   
  64.   
  65. import org.springframework.dao.DataAccessException;   
  66.   
  67. /**   
  68.  * @author rst   
  69.  *   
  70.  */   
  71. public interface CustomerDAO {   
  72.     public void add(Customer customer) throws DataAccessException;   
  73. }   
  74.   
  75. CustomerDAOImpl :   
  76.   
  77. package rst.spring.mock;   
  78.   
  79. import org.springframework.dao.DataAccessException;   
  80. import org.springframework.orm.hibernate.support.HibernateDaoSupport;   
  81.   
  82. /**   
  83.  * Class description.   
  84.  *   
  85.  * @author rst   
  86.  */   
  87. public class CustomerDAOHibernateImpl extends HibernateDaoSupport implements CustomerDAO{   
  88.        
  89.     public void add(Customer customer) throws DataAccessException{   
  90.         this.getHibernateTemplate().save(customer);   
  91.     }   
  92. }   
  93.   
<script type="text/javascript">render_code();</script>

 

然后测试的基类SpringDAOTestCase继承自AbstractTransactionalDataSourceSpringContextTests,目前只有一个指定测试用xml文件位置的逻辑。

代码
  1. package rst.spring.mock;   
  2.   
  3. import org.springframework.test.AbstractTransactionalDataSourceSpringContextTests;   
  4.   
  5. /**  
  6.  * Class description.  
  7.  *  
  8.  * @author rst  
  9.  */  
  10. public abstract class SpringDAOTestCase extends AbstractTransactionalDataSourceSpringContextTests {    
  11.   
  12.   protected String[] getConfigLocations() {    
  13.     return new String[] { "test.xml" };    
  14.   }    
  15.   
  16. }    
<script type="text/javascript">render_code();</script>

 

接着是我们真正测试的类CustomerDAOTest.java:

代码
  1. package rst.spring.mock;   
  2.   
  3. /**  
  4.  * Class description.  
  5.  *   
  6.  * @author rst  
  7.  */  
  8. public class CustomerDaoTest extends SpringDAOTestCase {   
  9.   
  10.     private CustomerDAOHibernateImpl customerDAO;   
  11.   
  12.     protected void onSetUpInTransaction() throws Exception {   
  13.         super.onSetUpInTransaction();   
  14.         //this.setPopulateProtectedVariables(true);   
  15.         customerDAO = (CustomerDAOHibernateImpl) this.applicationContext.getBean("customerDAO");   
  16.     }   
  17.   
  18.     protected void onTearDownInTransaction() {   
  19.         customerDAO = null;   
  20.     }   
  21.   
  22.     public void testInsert() {   
  23.         Customer customer = new Customer();   
  24.         customer.setName("javaeye");   
  25.         customerDAO.add(customer);   
  26.         String name = (String) jdbcTemplate.queryForObject("select name from customer where id=?"new Object[]{customer.getId()}, String.class);   
  27.           
  28.         assertEquals(customer.getName(), name);   
  29.     }   
  30.   
  31. }   
<script type="text/javascript">render_code();</script>

 

最后看看配置文件test.xml:

代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">  
  3.   
  4. <!--  
  5.   - Application context definition for Petclinic on Hibernate.  
  6.     -->  
  7. <beans>  
  8.   
  9.     <!-- ========================= RESOURCE DEFINITIONS ========================= -->  
  10.      
  11.     <!-- Configurer that replaces ${...} placeholders with values from a properties file -->  
  12.     <!-- (in this case, JDBC-related settings for the dataSource definition below) -->  
  13.     <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">  
  14.         <property name="location"><value>classpath:jdbc.properties</value></property>  
  15.     </bean>  
  16.   
  17.     <!-- Local DataSource that works in any environment -->  
  18.     <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">  
  19.         <property name="driverClassName"><value>${jdbc.driverClassName}</value></property>  
  20.         <property name="url"><value>${jdbc.url}</value></property>  
  21.         <property name="username"><value>${jdbc.username}</value></property>  
  22.         <property name="password"><value>${jdbc.password}</value></property>  
  23.     </bean>  
  24.   
  25.     <!-- Hibernate SessionFactory -->  
  26.     <bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean">  
  27.         <property name="dataSource"><ref local="dataSource"/></property>  
  28.         <property name="mappingResources">  
  29.             <value>rst/spring/mock/Customer.hbm.xml</value>  
  30.         </property>  
  31.         <property name="hibernateProperties">  
  32.             <props>  
  33.                 <prop key="hibernate.dialect">${hibernate.dialect}</prop>  
  34.                 <prop key="hibernate.show_sql">true</prop>  
  35.             </props>  
  36.         </property>  
  37.     </bean>  
  38.   
  39.     <!-- Transaction manager for a single Hibernate SessionFactory (alternative to JTA) -->  
  40.     <bean id="transactionManager" class="org.springframework.orm.hibernate.HibernateTransactionManager">  
  41.         <property name="sessionFactory"><ref local="sessionFactory"/></property>  
  42.     </bean>  
  43.        
  44.     <bean id="hibernateTemplate" class="org.springframework.orm.hibernate.HibernateTemplate">  
  45.         <property name="sessionFactory"><ref local="sessionFactory"/></property>  
  46.     </bean>  
  47.   
  48.     <bean id="customerDAO" class="rst.spring.mock.CustomerDAOHibernateImpl">  
  49.         <property name="hibernateTemplate"><ref local="hibernateTemplate"/></property>  
  50.     </bean>  
  51. </beans>  
<script type="text/javascript">render_code();</script>
这个文件很简单,不要忘记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如下:

代码
  1. package org.ggyy.web.test;   
  2.   
  3. import junit.framework.TestCase;   
  4.   
  5. import java.io.File;   
  6. import java.io.IOException;   
  7. import java.util.List;   
  8. import java.util.Map;   
  9.   
  10. import javax.servlet.http.HttpServletRequest;   
  11. import javax.servlet.http.HttpServletResponse;   
  12.   
  13. import junit.framework.TestCase;   
  14.   
  15. import org.apache.commons.logging.Log;   
  16. import org.apache.commons.logging.LogFactory;   
  17. import org.ggyy.bo.Cat;   
  18. import org.ggyy.web.ctrl.CatController;   
  19. import org.springframework.mock.web.MockHttpServletRequest;   
  20. import org.springframework.mock.web.MockHttpServletResponse;   
  21. import org.springframework.mock.web.MockServletContext;   
  22. import org.springframework.web.context.support.XmlWebApplicationContext;   
  23. import org.springframework.web.servlet.ModelAndView;   
  24.   
  25. public class ListCatTest extends TestCase {   
  26.     private static Log log = LogFactory.getLog(ListCatTest.class);   
  27.   
  28.     private XmlWebApplicationContext ctx;   
  29.   
  30.     public void setUp() {   
  31.         String[] paths = {   
  32.                 "file:/d:/eclipse/workspace/cat/WebRoot/WEB-INF/applicationContext.xml",   
  33.                 "file:/d:/eclipse/workspace/cat/WebRoot/WEB-INF/pet-servlet.xml" };   
  34.         ctx = new XmlWebApplicationContext();   
  35.         ctx.setConfigLocations(paths);   
  36.         ctx.setServletContext(new MockServletContext(""));   
  37.         ctx.refresh();   
  38.     }   
  39.   
  40.     public void testGetUsers() throws Exception {   
  41.         MockHttpServletRequest request = new MockHttpServletRequest();   
  42.         MockHttpServletResponse response = new MockHttpServletResponse();   
  43.         request.addParameter("parentId""2");   
  44.         CatController c = (CatController) ctx.getBean("catController");   
  45.         ModelAndView mav = c.listCatHandler(request, response);   
  46.         Map m = mav.getModel();   
  47. }   
  48. }   

<script type="text/javascript">render_code();</script>
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供大家观赏:

代码
  1. public abstract class AbstractClinicTests extends AbstractTransactionalDataSourceSpringContextTests {   
  2. protected Clinic clinic;   
  3. public void setClinic(Clinic clinic) {   
  4. this.clinic = clinic;   
  5. }   
  6. public void testGetVets() {   
  7. Collection vets = this.clinic.getVets();   
  8. assertEquals("JDBC query must show the same number of vets",   
  9. jdbcTemplate.queryForInt("SELECT COUNT(0) FROM VETS"),   
  10. vets.size());   
  11. Vet v1 = (Vet) EntityUtils.getById(vets, Vet.class2);   
  12. assertEquals("Leary", v1.getLastName());   
  13. assertEquals(1, v1.getNrOfSpecialties());   
  14. assertEquals("radiology", ((Specialty) v1.getSpecialties().get(0)).getName());   
  15. Vet v2 = (Vet) EntityUtils.getById(vets, Vet.class3);   
  16. assertEquals("Douglas", v2.getLastName());   
  17. assertEquals(2, v2.getNrOfSpecialties());   
  18. assertEquals("dentistry", ((Specialty) v2.getSpecialties().get(0)).getName());   
  19. assertEquals("surgery", ((Specialty) v2.getSpecialties().get(1)).getName());   
  20. }   

<script type="text/javascript">render_code();</script>
上面的clinic实例是自动注入的,

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值