在开发过程中进行单元测试的目的是为了让系统的更稳定。在实施测试驱动开发的时候发现一个问题,有些用例对数据有特定要求。因为测试过程本身会引起数据的变化,所以导致测试用例无法反复测试。
譬如添加一条主键id为10的记录:
测试用例可能是这样的 :
boolean handle= deptService.addDept(“10","测试部门10");
Assert.assertEquals(true,handle);
这个测试用例可以跑通,但是无法反复测试,因为第二次测试的时候就因为主键不能重复而报错。
解决方法:
我们可以通过手动还原测试用例修改的内容。在刚刚的例子中可以在每次测试完成后删除那条记录。有的人已经发现这个好像也太麻烦了吧,数据简单还好,如果是一个比较复杂的操作对多张数据表进行修改,那些个测试用例也太累了吧。所以还有一个可选方案就是使用回滚测试,让测试用例执行完之后并不对数据库进行修改,这样也能实现用例反复测试的效果,而且无需添加手动代码。
1 spring3环境配置成功2 可正常跑通junit测试
继承AbstractTransactionalJUnit4SpringContextTests类(通常spring3的单元测试类AbstractJUnit4SpringContextTests)
2.1在测试类的上方进行注解 @TransactionConfiguration(transactionManager="transactionManager",defaultRollback=false)2.2在需要回滚的方法上添加回滚标示 @Rollback(value=true)
如果不适用回滚测试的话 dataSource是可以不进行配置的,但是这里必须进行配置。(这个dataSource配置的是挺奇怪的,因为在sessionFactory配置项中已经指定hibernate.cfg.xml替代数据源配置了,不过不写这个dataSource是会报错的)
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="configLocation" value="classpath:hibernate.cfg.xml"> </property> </bean> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName"> <value>com.mysql.jdbc.Driver</value> </property> <property name="url"> <value>jdbc:mysql://localhost:3306/yusr?useUnicode=true&characterEncoding=UTF-8</value> </property> <property name="username"> <value>root</value> </property> <property name="password"> <value>root</value> </property> </bean> <!-- 配置事务管理 --> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory"> <ref bean="sessionFactory"/> </property> </bean> <!-- 配置事务的传播性 --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="add*" propagation="REQUIRED"/> <tx:method name="save*" propagation="REQUIRED"/> <tx:method name="remove*" propagation="REQUIRED"/> <tx:method name="update*" propagation="REQUIRED"/> <tx:method name="get*" propagation="REQUIRED"/> <tx:method name="find*" propagation="REQUIRED"/> <tx:method name="turn*" propagation="REQUIRED"/> <tx:method name="del*" propagation="REQUIRED"/> <tx:method name="move*" propagation="REQUIRED"/> <tx:method name="edit*" propagation="REQUIRED"/> <tx:method name="test*" propagation="REQUIRED"/> </tx:attributes> </tx:advice> <!-- 配置事务管理的哪些方法 --> <aop:config> <aop:pointcut id="allServiceMethod" expression="execution(* com.metecyu.*.dao.*.*(..)) or execution(* com.metecyu.*.service.*.*(..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="allServiceMethod"/> </aop:config> <!-- yzp:true:表示使用CGLib动态代理技术织入增强。不过即使proxy-target-class设置为false,如果目标类没有声明接口,则spring将自动使用CGLib动态代理(不过这个项目不加就会报错,其它项目都不需要,我想可能是包版本的关系)--> <aop:aspectj-autoproxy proxy-target-class="true" /> <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" /> <context:component-scan base-package="com.metecyu.yusr.dao" /> <context:component-scan base-package="com.metecyu.yusr.service" /> <!-- <context:component-scan base-package="com.megait.cw.task.service" /> <context:component-scan base-package="com.megait.xmgl.comm.service" /> --> </beans>
package com.metecyu.yusr.dao; import java.util.List; import javax.annotation.Resource; import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination; import org.apache.log4j.Logger; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.test.annotation.Rollback; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.transaction.TransactionConfiguration; import com.metecyu.yusr.model.Dept; import com.metecyu.yusr.service.DeptService; @TransactionConfiguration(transactionManager="transactionManager",defaultRollback=false) @ContextConfiguration(locations={"/applicationContext.xml","/hibernate.cfg.xml"}) public class DeptDAOTest extends AbstractTransactionalJUnit4SpringContextTests { private static final Logger log = Logger.getLogger(DeptDAOTest.class); @Resource private DeptDAO deptDAO; @Resource DeptService deptService; @Test @Rollback(value=true) public void testGetNewId(){ String deptid = "testDept"; String newDeptid = deptDAO.getNewDeptid(deptid); Assert.assertEquals("和原id相同",newDeptid, deptid); deptService.addDept(deptid,"测试部门","测试部门","1"); newDeptid = deptDAO.getNewDeptid(deptid); Assert.assertEquals("第一次id重复,编号为01",newDeptid, deptid+"@01"); deptService.addDept(deptid+"@01","测试部门@01","","1"); deptService.addDept(deptid+"@02","测试部门@02","","1"); deptService.addDept(deptid+"@03","测试部门@03","","1"); newDeptid = deptDAO.getNewDeptid(deptid); Assert.assertEquals("多条id重复,编号为当前末尾编号加1",newDeptid, deptid+"@04"); deptService.addDept(deptid+"@20","测试部门@20","","1"); newDeptid = deptDAO.getNewDeptid(deptid); Assert.assertEquals("多条id重复,编号为当前末尾编号加1",newDeptid, deptid+"@21"); deptService.addDept(deptid+"@99","测试部门@99","","1"); newDeptid = deptDAO.getNewDeptid(deptid); Assert.assertNotSame("第一次id重复,编号为01",newDeptid, deptid+"@00"); } @Test @Rollback(value=true) public void testGenarateDeptId() throws BadHanyuPinyinOutputFormatCombination{ String deptname = "测试部门"; String newDeptid = deptDAO.genarateDeptId(deptname); Assert.assertEquals("和原id相同",newDeptid, "csbm"); deptService.addDept("csbm","测试部门","测试部门","1"); newDeptid = deptDAO.genarateDeptId(deptname); Assert.assertEquals("第一次id重复,编号为01",newDeptid, "csbm@01"); } }