一、用例场景
如何你刚接手别人的代码、不熟悉代码业务逻辑、处理紧级异常或是不想按照一连串流程做用例测试数据等等开发场景情况下,可以考虑参考,反正我是刚刚运到了这么些个情况 - 代码逻辑比较混乱、不熟悉业务、没有很好的分层解耦合设计、时间有比较紧急、流程比较多...
二、源码分析
主要包括三个类接口文件:DevCodeAssistUtils.java、DefaultIniter.java、DefaultParameterIniter.java,接口类可以根据需要自定义
1.CodeDefaultInitUtils.java - 主工具代理初始化映射类,调用被代理类初始化方法
import java.util.concurrent.ConcurrentHashMap;@b@import java.util.concurrent.ConcurrentMap;@b@@b@import com.xwood.db.ConnectionDataSource;@b@@b@/**@b@ * .开发环境代码初始化补漏工具类@b@ * <dt>1.非开发环境请将isDevEnv设置为false</dt>@b@ * <dt>2.先在静态代码块注册类映射关系</dt>@b@ * <dt>3.在需走流程初始化mock数据,跳过异常</dt>@b@ * @author junni@b@ */@b@@SuppressWarnings("unchecked")@b@public class DevCodeAssistUtils implements DefaultIniter<Object>,DefaultParameterIniter<Object>{@b@ @b@ /**开发环境默认配置为true,其他发布之前需设置为false*/@b@ public static final boolean isDevEnv=true;@b@ @b@ private static ConcurrentMap<Class,Class<?>[]> invokeRefectProcessers=new ConcurrentHashMap<Class,Class<?>[]>();@b@ @b@ private static final String defaultProcessMethod="defaultInit";@b@ @b@ private DevCodeAssistUtils(){}@b@ @b@ /**初始化配置,如不配置默认注入无入参初始化方法*/@b@ static{@b@ invokeRefectProcessers.put(CodeDefaultInitUtils.class, new Class[]{});@b@ invokeRefectProcessers.put(ConnectionDataSource.class, new Class[]{String.class,String.class,String.class,String.class});@b@ }@b@ @b@ public static Object assign(Object assignObj,Object originalRetObj){@b@ if(!isDevEnv)@b@ return originalRetObj;@b@ return assignObj;@b@ }@b@ @b@ public static Object invoke(Object _this){@b@ return invoke(_this.getClass(),defaultProcessMethod,_this,null,new String[]{});@b@ }@b@ @b@ public static Object invoke(Object _this,Object originalRetObj){@b@ return invoke(_this.getClass(),defaultProcessMethod,_this,originalRetObj,new String[]{});@b@ }@b@ @b@ public static Object invoke(Object _this,Object... parameterValues){@b@ return invoke(_this.getClass(),defaultProcessMethod,_this,parameterValues);@b@ }@b@ @b@ public static Object invoke(Object _this,Object originalRetObj,Object... parameterValues){@b@ return invoke(_this.getClass(),defaultProcessMethod,_this,originalRetObj,parameterValues);@b@ }@b@ @b@ public static Object invoke(String method,Object _this,Object... parameterValues){@b@ return invoke(_this.getClass(),method,_this,null,parameterValues);@b@ }@b@ @b@ public static Object invoke(String method,Object _this,Object originalRetObj,Object... parameterValues){@b@ return invoke(_this.getClass(),method,_this,originalRetObj,parameterValues);@b@ }@b@ @b@ private static Object invoke(Class cla,String method,Object _this,Object originalRetObj,Object... parameterValues){@b@ if(!isDevEnv)@b@ return originalRetObj;@b@ try {@b@ return cla.getMethod(method,invokeRefectProcessers.get(cla)).invoke(_this, parameterValues);@b@ } catch (Exception e) {@b@ // TODO Auto-generated catch block@b@ e.printStackTrace();@b@ return originalRetObj;@b@ } @b@ }@b@ @b@@b@ @Override@b@ public Object defaultInit() {@b@ System.out.println("init.....");@b@ return null;@b@ }@b@@b@@b@ @Override@b@ public Object defaultInit(String... values) {@b@ // TODO Auto-generated method stub@b@ System.out.println("init...parameter:"+values);@b@ return null;@b@ @b@ }@b@@b@@b@ public static void main(String[] args) {@b@ DevCodeAssistUtils.invoke(new CodeDefaultInitUtils());@b@ }@b@@b@}
2.DefaultIniter.java - 无入参初始化方法接口,可以自己不使用,自定义标准
public interface DefaultIniter<T>{@b@ T defaultInit();@b@}
3.DefaultParameterIniter.java - 有参初始化方法接口,可以自己不使用,自定义标准
public interface DefaultParameterIniter<T>{@b@ T defaultInit(String... values);@b@}
三、用例代码
产品资源调用类用于从xml从获取配置资源返回数据,由于类加载方式获取类classpath路径,实际通过war包部署在weblogic目录下,临时调试工程目录获取不到对于路径资源配置文件,造成NullPointerException产生,现在用一个初始化方法在开发或测试环境躲避问题(开发环境CodeDefaultInitUtils的isDevEnv配置true,部署到生成或UAT环境需设为false)。
1.原始产品资源调用类ProductConfigConsumer.java - XmlUtils的getData因配置环境位置错误,强制返回空对象内容,造成了空指针产生
public ProductConfigConsumer{@b@ @b@ private String path=this.getClass().getResource("/product.xml").getPath();@b@ private String ruleVal="/products/product[@id='01']";@b@@b@ public List getData(){ @b@ return XmlUtils.getData(path,ruleVal); //产生NullPointerException@b@ }@b@@b@}
2.改造后资源调用类ProductConfigConsumer.java,从实际路径的产品id为02上获取对应数据
public ProductConfigConsumer implments DefaultIniter<String[]>{@b@ @b@ private String path=this.getClass().getResource("/product.xml").getPath();@b@ private String ruleVal="/products/product[@id='01']";@b@ @b@ private String[] mocks=(String[])DevCodeAssistUtils.invoke(this);@b@ @b@ @Override@b@ private String[] defaultInit(){@b@ return new String[]{"e:/ws/project/testProject/WebRoot/WEB-INF/classes/product.xml","/products/product[@id='02']"};@b@ }@b@@b@ public List getData(){ @b@ if(mocks!=null){@b@ path=mocks[0];@b@ ruleVal=mocks[1];@b@ }@b@ return XmlUtils.getData(path,ruleVal);@b@ }@b@@b@}
或
public ProductConfigConsumer{@b@ @b@ private String path=this.getClass().getResource("/product.xml").getPath();@b@ private String ruleVal="/products/product[@id='01']";@b@ @b@ @b@ public List getData(){ @b@ path=(String)DevCodeAssistUtils.assign("e:/ws/project/testProject/WebRoot/WEB-INF/classes/product.xml",path);@b@ ruleVal=(String)DevCodeAssistUtils.assign("/products/product[@id='02']",ruleVal);@b@ return XmlUtils.getData(path,ruleVal);@b@ }@b@@b@}