假如有2个Class,分别是A和B
public class A {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class B {
private A a;
private int c;
public A getA() {
return a;
}
public void setA(A a) {
this.a = a;
}
public int getC() {
return c;
}
public void setC(int c) {
this.c = c;
}
}
如果要把A的实例通过B的setA方法传入到B实例中,通过java代码是很容易实现的,但是如果通过fitnesse脚本来完成这个步骤的话,可以通过在slim框架中加入一个AConvert类,或者在Class A中新增一个获取实例的方法,显然,这2种方式都有弊端
弊端1. 如果通过加入AConvert的类实现的话,日后再次碰到类似的问题,还需要增加各种不同的Convert类
弊端2. 类似弊端1,每个Class下都要加入一个获取实例的方法,就会变得太繁琐,而且,如果是jar包中的类,就不能在该类中新增获取实例的方法
较好的解决方法:修改fitnesse源码,影响的Class:fitnesse.slim.SlimExecutionContext
红色部分是实现功能需要加入的代码
public class SlimExecutionContext {
private final FixtureInteraction interaction;
private Map<String, Object> instances = new HashMap<>();
private List<Library> libraries = new ArrayList<>();
private VariableStore variables = new VariableStore();
private List<String> paths = new ArrayList<>();
private List<String> auto_increment_variables = new ArrayList<>();
public SlimExecutionContext(FixtureInteraction interaction) {
this.interaction = interaction;
}
public List<Library> getLibraries() {
return Collections.unmodifiableList(libraries);
}
public void addLibrary(Library library) {
libraries.add(library);
}
public void setVariable(String name, MethodExecutionResult value) {
variables.setSymbol(name, value);
}
public MethodExecutionResult getVariable(String name) {
return variables.getSymbol(name);
}
public void setVariable(String name, Object value) {
setVariable(name, new MethodExecutionResult(value, Object.class));
}
public void create(String instanceName, String className, Object[] args)
throws SlimError, IllegalArgumentException, IllegalAccessException, InvocationTargetException,
InstantiationException {
Object potentialActor = variables.getStored(className);
if (potentialActor != null && !(potentialActor instanceof String)) {
addToInstancesOrLibrary(instanceName, potentialActor);
} else {
String replacedClassName = variables
.replaceSymbolsInString(className);
Object instance = interaction.createInstance(paths,
replacedClassName, replaceSymbols(args));
if(MyLog.isNewTest){/** * 跑Suite时,会同时跑多个wiki页面的脚本,所以需要回收上个wiki脚本产生的变量存储 */
for(String variable : auto_increment_variables){
variables.getVariables().remove(variable);
}
auto_increment_variables.clear();
MyLog.isNewTest = false;
}
/** * <span>当使用Slim的DecsionTable生成的实例时,会存储类名(classname)为变量名,对象实例为变量值到slim的上下文中,前端调用变量值,只需要$变量名</span> * <span>example: 页面声明一个DesicionTable,|com.test.Hello|,那么系统会增加一个变量名Hello,变量值为Hello实例的存储,如果再次声明DesicionTable,|com.test.Hello|,那么系统会增加一个为变量名Hello1的变量存储,前端调用分别使用$Hello和$Hello1,互不影响</span> */
if (className != null && className.contains(".")) {
String clzName = instance.getClass().getSimpleName();
String clz = genClassName(clzName);
MyLog.debug(String.format("set variable in SlimExecutionContext, variable name: [[%s]], class name: [[%s]]", clz, instance.getClass().getName()));
auto_increment_variables.add(clz);
setVariable(clz, instance);
}
}
}
/**
* 使DecisionTable产生的类实例的变量名不重复,保证一个类可以生成多个实例的变量
*
* @param clzName
* @return
*/
private String genClassName(String clzName) {
String tmp = clzName;
int i = 1;
while (variables.getVariables().containsKey(tmp)) {
tmp = clzName + i;
i++;
}
return tmp;
}
public void addPath(String path) {
if (!paths.contains(path)) {
paths.add(0, path);
}
}
public Object getInstance(String instanceName) {
Object instance = instances.get(instanceName);
if (instance != null) {
return instance;
}
for (Library library : libraries) {
if (library.instanceName.equals(instanceName)) {
return library.instance;
}
}
throw new SlimError(String.format("message:<<%s %s>>",
SlimServer.NO_INSTANCE, instanceName));
}
private void addToInstancesOrLibrary(String instanceName, Object instance) {
if (isLibrary(instanceName)) {
libraries.add(new Library(instanceName, instance));
} else {
setInstance(instanceName, instance);
}
}
public void setInstance(String instanceName, Object instance) {
instances.put(instanceName, instance);
}
private boolean isLibrary(String instanceName) {
return instanceName.startsWith("library");
}
public Object[] replaceSymbols(Object[] args) {
return variables.replaceSymbols(args);
}
public FixtureInteraction getInteraction() {
return interaction;
}
}
wiki脚本
TdParamData、TdParamData1、TdParamData2是DecisionTable中com.qf.pboc.dao.entity.td.TdParamData类的3个实例,因为申明了3次
!define name1 {1-1}
!define name2 {1-2}
!define name3 {1-3}
|!-com.qf.pboc.dao.entity.td.TdParamData-!|
|name |mobile |
|${name1} |13312312312 |
|!-com.qf.pboc.dao.entity.td.TdParamData-!|
|name |mobile |
|${name2} |14312312312 |
|!-com.qf.pboc.dao.entity.td.TdParamData-!|
|name |mobile |
|${name3} |15312312312 |
|script|common util |
|show |getValue;|$TdParamData|name |
|show |getValue;|$TdParamData|mobile|
|script|common util |
|show |getValue;|$TdParamData1|name |
|show |getValue;|$TdParamData1|mobile|
|script|common util |
|show |getValue;|$TdParamData2|name |
|show |getValue;|$TdParamData2|mobile|
执行结果