基于junit的业务流程单元测试工具
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?xml version="1.0" encoding="UTF-8"?> <config> <!--参数列表 --> <data name="inshopProductPromRuleRpc"> <!-- 参数properties的属性定义: name:参数名称 必须定义 type:参数类型(1代表对应的方法有多个参数,反之为参数的具体类型名称) params:参数节点(若父节点properties为指定的Vo等对象类型,则定义Type为1,typeclass为该Vo的具体类型名称; 若参数类型为java.lang.String、java.lang.Integer、java.lang.Float、 java.lang.Doubl、java.math.BigDecimal、java.util.Date、java.sql.Timestamp、java.lang.Boolean 、java.lang.Long,直接指定参数type为0,typeclass为对应的class即可。 --> <properties name="参数1" type="com.yhd.inshop.rpc.model.promotion.InshopProductPromRuleRpc"> <productId type="0">1707235</productId> <merchantId type="0">423</merchantId> <productPromNonMemPrice type="0">50</productPromNonMemPrice> <backOperatorId type="0">1000</backOperatorId> <productPromStartDate type="0">2014-5-19 15:58:46</productPromStartDate> <productPromEndDate type="0">2014-6-04 15:58:55</productPromEndDate> <isAttachShippingProm type="0">1</isAttachShippingProm> <dto type="1" typeclass="com.yhd.inshop.rpc.model.promotion.InshopProductPromRuleRpc"> <reason type="0" typeclass="java.lang.Long">取消成功</reason> <status type="0" typeclass="java.lang.Long">3</status> <isDeleted type="0" typeclass="java.lang.Long">1</isDeleted> <isSync type="0" typeclass="java.lang.Long">1</isSync> <relateId type="0" typeclass="java.lang.Long">1201015</relateId> <id type="0" typeclass="java.lang.Long">106319</id> <updateTime type="0" typeclass="java.util.Date">2012-6-27 17:57:41</updateTime> <backOperatorId type="0" typeclass="java.lang.Long">3000</backOperatorId> </dto> </properties> <properties name="参数3" type="-1" > <productId type="0" typeclass="java.lang.Long">1201015</productId> <merchantId type="0" typeclass="java.lang.Long">1186</merchantId> <productPromNonMemPrice type="0" typeclass="java.lang.Double">70</productPromNonMemPrice> <backOperatorId type="0" typeclass="java.lang.Long">3000</backOperatorId> <productPromStartDate type="0" typeclass="java.util.Date">2015-5-19 15:58:46</productPromStartDate> <productPromEndDate type="0" typeclass="java.util.Date">2015-6-04 15:58:55</productPromEndDate> <isAttachShippingProm type="0" typeclass="java.lang.Integer">1</isAttachShippingProm> </properties> <properties name="参数4" type="-1"> <params type="1" typeclass="com.yhd.inshop.rpc.model.promotion.InshopProductPromRuleRpc"> <reason type="0" typeclass="java.lang.Long">取消成功</reason> <status type="0" typeclass="java.lang.Long">3</status> <isDeleted type="0" typeclass="java.lang.Long">1</isDeleted> <isSync type="0" typeclass="java.lang.Long">1</isSync> <relateId type="0" typeclass="java.lang.Long">1201015</relateId> <id type="0" typeclass="java.lang.Long">106319</id> <updateTime type="0" typeclass="java.util.Date">2012-6-27 17:57:41</updateTime> <backOperatorId type="0" typeclass="java.lang.Long">3000</backOperatorId> <dto type="1" typeclass="com.yhd.inshop.rpc.model.promotion.InshopProductPromRuleRpc"> <reason type="0" typeclass="java.lang.Long">取消成功</reason> <status type="0" typeclass="java.lang.Long">3</status> <isDeleted type="0" typeclass="java.lang.Long">1</isDeleted> <isSync type="0" typeclass="java.lang.Long">1</isSync> <relateId type="0" typeclass="java.lang.Long">1201015</relateId> <id type="0" typeclass="java.lang.Long">106319</id> <updateTime type="0" typeclass="java.util.Date">2012-6-27 17:57:41</updateTime> <backOperatorId type="0" typeclass="java.lang.Long">3000</backOperatorId> </dto> </params> <params type="0" typeclass="java.lang.Integer">1</params> </properties> <properties name="参数5" type="-1"> <params type="0" typeclass="java.lang.Long">106400</params> </properties> <properties name="参数6" type="com.yhd.inshop.rpc.dto.promotion.InshopProductPromRuleRpcDto"> <promType type="0">1</promType> <merchantId type="0" typeclass="java.lang.Long">1186</merchantId> </properties> </data> <!--测试的目标入口方法() --> <function> <childfunction name="findInshopProductPromListWithPgService" parametertype="参数6" /> <childfunction name="saveInshopProductPromRuleService" parametertype="参数1" /> <!--如果方法执行有返回值,程序会将返回值采用BeanUtil.copy的方式将返回值对应拷贝到parentproperties父参数中,适用于查询Vo parameterName 代表从父参数中获取数据的属性,parametervalue代表方法参数定义的顺序;如果方法定义的参数中含有嵌套Vo, parameterName依然对应需要取值的属性,parametervalue定义嵌套Vo的参数序号,以0开始 如果不执行insert,直接执行update函数,必须先定义参数1,参数1对应的typeClass为update的参数类型 然后执行对应的find方法找出需要修改的数据,find对应的parentproperties参数为“参数1” --> <childfunction name="findInshopProductPromRuleByIdService" parametertype="参数5" parentproperties="参数1" parameterName="id" parametervalue="0"/> <!-- isremedy方法执行失败是否执行数据补救 type=set 表示将parametertype定义的参数值映射到parentproperties父参数对应的属性中去(如果是 父参数的type为-1,则按照顺序进行赋值) parameterName代表需要映射的属性,与parametertype定义的参数列表顺序保持一致 --> <childfunction name="updateInshopProductPromRuleService" parametertype="参数3" isremedy="1" parentproperties="参数1" type="set" parameterName="productId,merchantId,productPromNonMemPrice,backOperatorId,productPromStartDate,productPromEndDate,isAttachShippingProm" parametervalue="1300000,1185,50.00,1000,2017-5-19 15:58:46,2017-6-4 15:58:55,1" /> <childfunction name="findInshopProductPromRuleByIdService" parametertype="参数5" parentproperties="参数1" parameterName="id" parametervalue="0"/> <childfunction name="cancelInshopProductPromRule" parametertype="参数4" isremedy="0" parentproperties="参数1" parameterName="id,updateTime" parametervalue="0,0"/> <!-- 数据删除 --> <childfunction name="deleteInshopProductPromRuleForId" parametertype="参数5" parentproperties="参数1" parameterName="id" parametervalue="0"/> </function> <service type="com.yhd.inshop.rpc.service.promotion.impl.InshopProductPromRuleRpcServiceImpl"/> <!-- 数据补救函数 删除insert进去的数据--> <endfunction name="deleteInshopProductPromRuleForId" parametertype="参数5" parentproperties="参数1" parameterName="id" parametervalue="0"/> </config>
前段时间应公司需求,要弄个junit的单元测试工具,从数据准备到数据销毁,可配置的东西。后来折腾了2天总算弄出来了,虽然比较粗糙,但是已经基本上可以用了。呵呵 先放在这记下来 ,后面边优化边记下来。暂时先附上模板XML配置文件,后续在上代码
支持文件类型:XML格式
节点备注:
<Data>:参数集标签;
<Properties>:参数标签(测试方法对应的参数)
<Function>:方法集标签
<Childfunction>:方法标签(需要进行测试的方法)
<service>:需要进行测试的Service实现类
< endfunction>: 数据补救方法
节点内部属性备注:
Data. Name:参数集的名称(必须)
Properties. Name:参数标识名称(必须)
Properties .type:参数类型
备注:1、若对应的方法声明格式为:int cancelInshopProductPromRule(InshopProductPromRuleRpc inshopProductPromRule,Integer cancelType),该属性值为1
2、若对应方法声明格式为: void saveInshopProductPromRuleService(InshopProductPromRuleRpc inshopProductPromRuleRpc),改属性值为参数中inshopProductPromRuleRpc
的完整类型名称:com.yhd.inshop.rpc.model.promotion.InshopProductPromRuleRpc
注意:
A、若方法中的参数声明格式为2中的格式,对其进行参数声明时,采用以下格式:
<properties name="参数1" type="com.yhd.inshop.rpc.model.promotion.InshopProductPromRuleRpc">
<productId type="0">1201014</productId>
<merchantId type="0">1185</merchantId>
<productPromNonMemPrice type="0">50</productPromNonMemPrice>
<backOperatorId type="0">1000</backOperatorId>
<productPromStartDate type="0">2014-5-19 15:58:46</productPromStartDate>
<productPromEndDate type="0">2014-6-04 15:58:55</productPromEndDate>
<isAttachShippingProm type="0">1</isAttachShippingProm>
</properties>
每个字参数节点的名称对应type类型的中的属性名称,type为0代表可以直接进行转换的类型;
B、若方法的参数声明格式为1中的格式,在对其进行参数声明时,可以支持嵌套VO的形式进行声明,具体格式如下:
<properties name="参数4" type="-1">
<params type="1" typeclass="com.yhd.inshop.rpc.model.promotion.InshopProductPromRuleRpc">
<reason type="0" typeclass="java.lang.Long">取消成功</reason>
<status type="0" typeclass="java.lang.Long">3</status>
<isDeleted type="0" typeclass="java.lang.Long">1</isDeleted>
<isSync type="0" typeclass="java.lang.Long">1</isSync>
<relateId type="0" typeclass="java.lang.Long">1201015</relateId>
<id type="0" typeclass="java.lang.Long">106319</id>
<updateTime type="0" typeclass="java.util.Date">2012-6-27 17:57:41</updateTime>
<backOperatorId type="0" typeclass="java.lang.Long">3000</backOperatorId>
</params>
<params type="0" typeclass="java.lang.Integer">1</params>
</properties>
若参数列表中单个参数为具体的嵌套VO对象,请将该参数的type属性指定为1,typeclass为该嵌套VO的具体实现类型名称;反之若参数类型为以下类型:
java.lang.String、java.lang.Integer、java.lang.Float、java.lang.Double、java.math.BigDecimal、java.util.Date、java.sql.Timestamp、java.lang.Boolean、java.lang.Long
则该参数的type指定为0,统一认为可以直接转换的参数类型,typeclass为对应的类型名称;
Childfunction. Name:需要执行的方法声明名称;
Childfunction .parametertype:方法对应的参数声明类型
Childfunction .parentproperties:方法声明参数的父参数,若改方法有返回值,则在该方法执行成功后,会将该父参数的数据值采用BeanUtil.copy(a,b)的方式进行属性值copy重新赋值;
Childfunction. Type:对父参数的属性值的操作方式,为null或者Set则代表向父参数中赋值,为get则代表从父参数中取值,与parameterName、Parametervalue、parametertype配合使用,
若该方法绑定了parametertype属性则在取值时从parametertype中取值,依次向parameterName定义的属性字段名称进行赋值;
Childfunction. parameterName:对应于父参数的属性Name,与parentproperties配合使用,支持逗号分隔的多参数形式:productId,merchantId,productPromNonMemPrice……….
Childfunction. Parametervalue:对应于parameterName属性的Value,支持逗号分隔的多参数形式:1,2,3…….
Childfunction .isremedy:方法执行失败后是否执行数据补救方法,0代表执行;1代表不执行。
< service >:需要测试的目标Service,必须定义type属性。例如:<service type="com.yhd.inshop.rpc.service.promotion.impl.InshopProductPromRuleRpcServiceImpl"/>
< endfunction >:数据补救方法声明,声明格式同Childfunction声明;
实际应用步骤:
1 声明junit的数据来源,即数据准备文件,目前只支持XML格式的声明;
例如:
#声明junit测试数据准备文件地址
junitData=D:\\junit\\junitData.xml
2 配置junitManager实现Bean
<bean id="junitManager" class="com.yhd.inshop.common.utils.junit.JunitManager">
<property name="dataPath"><value>${junitData}</value></property>
<property name="serviceObj" ref="inshopProductPromRuleRpcService"/>
</bean>
注入属性声明:
dataPath:数据准备文件来源路径
serviceObj:测试目标的Service对象,由于现在的测试环境采用Spring注入的方式,所以如果直接采用反射的方式生成Service对象,无法取得Service中的其他Bean的对象。
3、新建一个junit的单元测试类
private ApplicationContext ac;
private JunitManager junitManager;
@Before
public void setUp() throws Exception {
ac = new ClassPathXmlApplicationContext("classpath:spring/applicationContext-promotion-deploy.xml");
junitManager=(JunitManager)ac.getBean("junitManager");
}
@Test
public void test() throws ParseException {
try{
junitManager.setUp();
}catch(Exception e) {
}
4、在模板文件对需要测试的方法、参数等进行定义,然后RUN执行,junit测试执行时,会打印每个方法的执行情况,包含传入的参数、返回值等信息。
测试环境执行日志输出: