网站网页设计哪个好,网站建设销售总结,网站做js跳转,nas上建设网站项目文件结构图#xff1a; 椭圆框中的Jar 包是单元测试时候需要引入的。
矩形框 MainTest 每个包下一个#xff0c;为 JUnit4 的 Suite 套件#xff0c;其作用是执行本包下的“测试类”和子包的 MainTest。
例如#xff1a;jp.co.snjp.ht.MainTest package jp.co.snjp.h…项目文件结构图 椭圆框中的Jar 包是单元测试时候需要引入的。
矩形框 MainTest 每个包下一个为 JUnit4 的 Suite 套件其作用是执行本包下的“测试类”和子包的 MainTest。
例如jp.co.snjp.ht.MainTest package jp.co.snjp.ht;import org.junit.runner.RunWith;
import org.junit.runners.Suite;RunWith( Suite.class )
Suite.SuiteClasses({ jp.co.snjp.ht.orderCheck.MainTest.class, jp.co.snjp.ht.outPreconcert.MainTest.class,jp.co.snjp.ht.partOut.MainTest.class,jp.co.snjp.ht.productCheck.MainTest.class,
})
public class MainTest {
}由于 jp.co.snjp.ht 包下没有“测试类”因而只需要引入“子包”的 MainTest 即可而jp.co.snjp.ht.orderCheck.MainTest package jp.co.snjp.ht.orderCheck;import org.junit.runner.RunWith;
import org.junit.runners.Suite;RunWith( Suite.class )
Suite.SuiteClasses({ CheckBarcodeTest.class, OrderConfirmTest.class
})
public class MainTest {}由于 jp.co.snjp.ht.orderCheck 下没有“子包”因而只需要引入“测试类”————————————————————————————————
Strut2 提供了隔离容器对象的方法因而在所有Action 的基类将其织入。
因为本项目很小没有单独的Business 层和DAO 层业务逻辑在 Action 中完成SQL 操作在 SqlHelper 中完成。
为了实现单元测试隔离测试效果这里提供了 setSqlHelper( SqlHelper sqlHelper ) 方法这样就可以传入模拟的 SqlHelper 对象 package jp.co.snjp.ht.util;import java.util.Date;
import java.util.List;
import java.util.Map;import jp.co.snjp.dao.SqlHelper;import org.apache.struts2.interceptor.CookiesAware;
import org.apache.struts2.interceptor.RequestAware;
import org.apache.struts2.interceptor.SessionAware;import com.opensymphony.xwork2.ActionSupport;public class BaseAction extends ActionSupport implements RequestAware,SessionAware,CookiesAware{private static final long serialVersionUID 1L;protected MapString,Object requestMap;protected MapString,Object sessionMap;protected MapString,String cookieMap;/*** 查询结果集*/protected ListObject list;/*** SQL 执行帮助类*/protected SqlHelper sqlHelper;public void setRequest(MapString, Object requestMap) {this.requestMap requestMap;}public void setSession(MapString, Object sessionMap) {this.sessionMap sessionMap;}public void setCookiesMap(MapString, String cookieMap) {this.cookieMap cookieMap;}public void setSqlHelper( SqlHelper sqlHelper ){this.sqlHelper sqlHelper;}/*** 记录存储过程执行的日志信息* param start* param name** Date :2012-6-7* Author :GongQiang* throws Exception */protected void logStroeProcedure( Date start, String name ) throws Exception{String formatDateTime Utils.formatDateTime( start );String userId (String) sessionMap.get( user_id );String sql insert into HT_CCGC_LOG(usercode,ccgcmc,kszxsj) values ( userId , name , formatDateTime );;sqlHelper.executeSQL( sql );}
}虽然提供了 setSqlHelper( SqlHelper sqlHelper ) 方法但是这方法在什么时候调用呢 为了解决这个问题就只能把实际的业务逻辑放到 doExecute() 方法下去执行而在 execute()方法下调用 setSqlHelper()方法只用测试 doExecute()方法。
doExecute()方法修饰为包可见这样就只有测试代码可以访问。代码如下 package jp.co.snjp.ht.productCheck;import java.math.BigDecimal;
import java.util.List;
import java.util.Map;import jp.co.snjp.dao.SqlHelper;
import jp.co.snjp.ht.util.BaseAction;
import jp.co.snjp.ht.util.SpotTicketBarcodeParser;
/*** 部品检查录入-Barcode扫描Action* author GongQiang**/
public class ProductCheckBarcode extends BaseAction {private static final long serialVersionUID 1L;private String barcode;private String backUrl;public String getBarcode() {return barcode;}public void setBarcode(String barcode) {this.barcode barcode;}public String getBackUrl() {return backUrl;}public void setBackUrl(String backUrl) {this.backUrl backUrl;}/*** error_0 条码不符合规则* error_1 订单在DB中不存在 或 订单已经执行完毕* error_2 订单区分错误*/Overridepublic String execute() throws Exception {super.execute();setBackUrl( productCheck/scanBarcode.jsp );setSqlHelper( new SqlHelper() );return doExecute();}String doExecute()throws Exception {SpotTicketBarcodeParser parser new SpotTicketBarcodeParser( barcode );if( ! parser.valid() ){return error_0;}queryOrderInfo( parser.getOrderNo() );if( orderNotExist() || orderFinished() ){return error_1;}if( !checkDistinguish() ){return error_2;}sessionMap.put( order_info, list.get(0) );return SUCCESS;}void queryOrderInfo( String orderNo ) throws Exception{String sql select top 1 * from iOrder_Check where OrderNo orderNo ;;list sqlHelper.executeQuery( sql );if( list null || list.isEmpty() ){return;}queryNameCount(orderNo);}/*** 查询订单名称 和 订单残实收数量* ** Date :2012-6-8* Author :GongQiang* throws Exception */private void queryNameCount( String orderNo ) throws Exception{String sql select sum(nqty) as usedCount from iOrder_Check where orderno orderNo group by orderno;;List usedCountResult sqlHelper.executeQuery( sql );BigDecimal orderCount (BigDecimal) ((Map)list.get(0)).get( pqty );BigDecimal usedCount (BigDecimal) ((Map)usedCountResult.get(0)).get( usedcount );BigDecimal remainCount orderCount.subtract( usedCount );sql select itemname from iorder_operate where OrderNo orderNo ;;List itemNameResult sqlHelper.executeQuery( sql );String itemName (String) ((Map)itemNameResult.get(0)).get( itemname );((Map)list.get(0)).put( remaincount, remainCount );((Map)list.get(0)).put( usedcount, usedCount );((Map)list.get(0)).put( itemname, itemName );}/*** DB中没有关联的订单* return** Date :2012-6-7* Author :GongQiang*/boolean orderNotExist(){if( list null || list.isEmpty() ){return true;}return false;}/*** 该订单已经执行完毕* return** Date :2012-6-7* Author :GongQiang*/boolean orderFinished(){BigDecimal remainCountInOrder (BigDecimal)((Map)list.get(0)).get( remaincount );if( remainCountInOrder ! null ){return remainCountInOrder.compareTo( new BigDecimal(0) ) 0 ;}return false;}/*** 检查区分是否正确* return** Date :2012-6-7* Author :GongQiang*/private boolean checkDistinguish(){String[] rights { 保证 };String dist (String) ((Map)list.get(0)).get( chkdistinguish );for( int i0 ; irights.length ; i ){if( rights[i].equals( dist ) ){return true;}}return false;}
}
逻辑很简单这里仅仅测试最基本的4 条执行路径
1、条码解析错误
2、订单在DB中不存在
3、订单已经执行完成
4、分区错误
5、OK
下面是完整的测试类 package jp.co.snjp.ht.productCheck;import static org.junit.Assert.*;import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;import jp.co.snjp.dao.SqlHelper;import org.easymock.classextension.EasyMock;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;public class ProductCheckBarcodeTest {BeforeClasspublic static void setUpBeforeClass() throws Exception {}AfterClasspublic static void tearDownAfterClass() throws Exception {}/*** 错误条码* ** Date :2012-6-18* Author :GongQiang* throws Exception */Testpublic void testDoExecute_errorBarcode() throws Exception {ProductCheckBarcode action new ProductCheckBarcode();action.setBarcode( xxx0001 );assertEquals(error_0, action.doExecute() );action new ProductCheckBarcode();action.setBarcode( 0123456789012345678901234567890123456789555 );assertEquals(error_0, action.doExecute() );}/*** DB中没有关联的记录* ** Date :2012-6-18* Author :GongQiang* throws Exception */Testpublic void testDoExecute_noRecord() throws Exception {SqlHelper mockSqlHelper EasyMock.createMock( SqlHelper.class );// 返回结果EasyMock.expect( mockSqlHelper.executeQuery( (String)EasyMock.anyObject() )).andReturn( new ArrayListMapString,Object() );// ReplayEasyMock.replay( mockSqlHelper );ProductCheckBarcode action new ProductCheckBarcode();action.setBarcode( xxx0001|bbb );action.setSqlHelper( mockSqlHelper );assertEquals(error_1, action.doExecute() );//VerifyEasyMock.verify( mockSqlHelper );//-----------------------------------------mockSqlHelper EasyMock.createMock( SqlHelper.class );// 返回结果EasyMock.expect( mockSqlHelper.executeQuery( (String)EasyMock.anyObject() )).andReturn( null );// ReplayEasyMock.replay( mockSqlHelper );action new ProductCheckBarcode();action.setBarcode( xxx0001|bbb );action.setSqlHelper( mockSqlHelper );assertEquals(error_1, action.doExecute() );//VerifyEasyMock.verify( mockSqlHelper );}/*** 记录已经执行完毕* ** Date :2012-6-18* Author :GongQiang* throws Exception */Testpublic void testDoExecute_finished() throws Exception {//list -- 返回的结果集MapString, Object map new HashMapString,Object();map.put(pqty, new BigDecimal(100)); //订单关联数量map.put(usedcount, new BigDecimal(100)); //已经使用数量 --剩余数量就是0map.put(itemname, TextOrderXXX);ListMapString,Object list new ArrayListMapString,Object();list.add( map );SqlHelper mockSqlHelper EasyMock.createMock( SqlHelper.class );EasyMock.expect( mockSqlHelper.executeQuery( (String)EasyMock.anyObject() )).andReturn( list ).times(3);// ReplayEasyMock.replay( mockSqlHelper );ProductCheckBarcode action new ProductCheckBarcode();action.setBarcode( xxx0001|bbb );action.setSqlHelper( mockSqlHelper );assertEquals(error_1, action.doExecute() );//VerifyEasyMock.verify( mockSqlHelper );}/*** 错误的分区* ** Date :2012-6-18* Author :GongQiang* throws Exception */Testpublic void testDoExecute_errorDistinguish() throws Exception {//list -- 返回的结果集MapString, Object map new HashMapString,Object();map.put(pqty, new BigDecimal(100)); //订单关联数量map.put(usedcount, new BigDecimal(50)); //已经使用数量 --剩余数量就是50map.put(itemname, TextOrderXXX);map.put( chkdistinguish, 不存在 );ListMapString,Object list new ArrayListMapString,Object();list.add( map );SqlHelper mockSqlHelper EasyMock.createMock( SqlHelper.class );EasyMock.expect( mockSqlHelper.executeQuery( (String)EasyMock.anyObject() )).andReturn( list ).times(3);// ReplayEasyMock.replay( mockSqlHelper );ProductCheckBarcode action new ProductCheckBarcode();action.setBarcode( xxx0001|bbb );action.setSqlHelper( mockSqlHelper );assertEquals(error_2, action.doExecute() );//VerifyEasyMock.verify( mockSqlHelper );}/*** 正常* ** Date :2012-6-18* Author :GongQiang* throws Exception */Testpublic void testDoExecute_ok() throws Exception {//list -- 返回的结果集MapString, Object map new HashMapString,Object();map.put(pqty, new BigDecimal(100)); //订单关联数量map.put(usedcount, new BigDecimal(50)); //已经使用数量 --剩余数量就是50map.put(itemname, TextOrderXXX);map.put( chkdistinguish, 保证 );ListMapString,Object list new ArrayListMapString,Object();list.add( map );SqlHelper mockSqlHelper EasyMock.createMock( SqlHelper.class );EasyMock.expect( mockSqlHelper.executeQuery( (String)EasyMock.anyObject() )).andReturn( list ).times(3);// ReplayEasyMock.replay( mockSqlHelper );ProductCheckBarcode action new ProductCheckBarcode();action.setBarcode( xxx0001|bbb );action.setSqlHelper( mockSqlHelper );action.setSession( new HashMapString,Object() );assertEquals(success, action.doExecute() );//VerifyEasyMock.verify( mockSqlHelper );}
}下面详细讲解测试方法的写法1、条码解析错误 /*** 错误条码* ** Date :2012-6-18* Author :GongQiang* throws Exception */Testpublic void testDoExecute_errorBarcode() throws Exception {ProductCheckBarcode action new ProductCheckBarcode();action.setBarcode( xxx0001 );assertEquals(error_0, action.doExecute() );action new ProductCheckBarcode();action.setBarcode( 0123456789012345678901234567890123456789555 );assertEquals(error_0, action.doExecute() );}当条码解析错误时查询没有机会执行也就没有必要传入 SqlHelper 对象。2、订单在DB中不存在 /*** DB中没有关联的记录* ** Date :2012-6-18* Author :GongQiang* throws Exception */Testpublic void testDoExecute_noRecord() throws Exception {SqlHelper mockSqlHelper EasyMock.createMock( SqlHelper.class );// 返回结果EasyMock.expect( mockSqlHelper.executeQuery( (String)EasyMock.anyObject() )).andReturn( new ArrayListMapString,Object() );// ReplayEasyMock.replay( mockSqlHelper );ProductCheckBarcode action new ProductCheckBarcode();action.setBarcode( xxx0001|bbb );action.setSqlHelper( mockSqlHelper );assertEquals(error_1, action.doExecute() );//VerifyEasyMock.verify( mockSqlHelper );//-----------------------------------------mockSqlHelper EasyMock.createMock( SqlHelper.class );// 返回结果EasyMock.expect( mockSqlHelper.executeQuery( (String)EasyMock.anyObject() )).andReturn( null );// ReplayEasyMock.replay( mockSqlHelper );action new ProductCheckBarcode();action.setBarcode( xxx0001|bbb );action.setSqlHelper( mockSqlHelper );assertEquals(error_1, action.doExecute() );//VerifyEasyMock.verify( mockSqlHelper );}为了实现单元测试的隔离性这里使用了模拟的 SqlHelper 对象。模拟返回一个空的List 或者 null。注意模拟方法执行时候是严格的参数匹配的为简易性这里直接使用 EasyMock.anyObject()这样任何参数都能匹配执行。 3、订单已经执行完成 /*** 记录已经执行完毕* ** Date :2012-6-18* Author :GongQiang* throws Exception */Testpublic void testDoExecute_finished() throws Exception {//list -- 返回的结果集MapString, Object map new HashMapString,Object();map.put(pqty, new BigDecimal(100)); //订单关联数量map.put(usedcount, new BigDecimal(100)); //已经使用数量 --剩余数量就是0map.put(itemname, TextOrderXXX);ListMapString,Object list new ArrayListMapString,Object();list.add( map );SqlHelper mockSqlHelper EasyMock.createMock( SqlHelper.class );EasyMock.expect( mockSqlHelper.executeQuery( (String)EasyMock.anyObject() )).andReturn( list ).times(3);// ReplayEasyMock.replay( mockSqlHelper );ProductCheckBarcode action new ProductCheckBarcode();action.setBarcode( xxx0001|bbb );action.setSqlHelper( mockSqlHelper );assertEquals(error_1, action.doExecute() );//VerifyEasyMock.verify( mockSqlHelper );}在实际代码中当查询到记录时就要继续两个 SQL查询操作1、查询订单名称2、查询订单关联数量和已经检查数量。并依次往 list 结果集中添加对象但是在测试中为了方便起见直接
一次性构造出完整的结果并
重复执行 3次。4、分区错误 /*** 错误的分区* ** Date :2012-6-18* Author :GongQiang* throws Exception */Testpublic void testDoExecute_errorDistinguish() throws Exception {//list -- 返回的结果集MapString, Object map new HashMapString,Object();map.put(pqty, new BigDecimal(100)); //订单关联数量map.put(usedcount, new BigDecimal(50)); //已经使用数量 --剩余数量就是50map.put(itemname, TextOrderXXX);map.put( chkdistinguish, 不存在 );ListMapString,Object list new ArrayListMapString,Object();list.add( map );SqlHelper mockSqlHelper EasyMock.createMock( SqlHelper.class );EasyMock.expect( mockSqlHelper.executeQuery( (String)EasyMock.anyObject() )).andReturn( list ).times(3);// ReplayEasyMock.replay( mockSqlHelper );ProductCheckBarcode action new ProductCheckBarcode();action.setBarcode( xxx0001|bbb );action.setSqlHelper( mockSqlHelper );assertEquals(error_2, action.doExecute() );//VerifyEasyMock.verify( mockSqlHelper );}这里就是注意构造参数使得前面的判断都成功到这里判断分区时错误。5、OK /*** 正常* ** Date :2012-6-18* Author :GongQiang* throws Exception */Testpublic void testDoExecute_ok() throws Exception {//list -- 返回的结果集MapString, Object map new HashMapString,Object();map.put(pqty, new BigDecimal(100)); //订单关联数量map.put(usedcount, new BigDecimal(50)); //已经使用数量 --剩余数量就是50map.put(itemname, TextOrderXXX);map.put( chkdistinguish, 保证 );ListMapString,Object list new ArrayListMapString,Object();list.add( map );SqlHelper mockSqlHelper EasyMock.createMock( SqlHelper.class );EasyMock.expect( mockSqlHelper.executeQuery( (String)EasyMock.anyObject() )).andReturn( list ).times(3);// ReplayEasyMock.replay( mockSqlHelper );ProductCheckBarcode action new ProductCheckBarcode();action.setBarcode( xxx0001|bbb );action.setSqlHelper( mockSqlHelper );action.setSession( new HashMapString,Object() );assertEquals(success, action.doExecute() );//VerifyEasyMock.verify( mockSqlHelper );}这里要注意因为实际代码中 调用了sessionMap 的put 方法因而这里就要传入一个对象。————————————————————————————————————扩展当有单独的 Business 层和 DAO 层时候。也许没有办法像 SqlHelper 简单的只需要一个接口方法即可也许就要每个子 Action 设置相应的Business 对象。