mirror of
https://github.com/alibaba/testable-mock.git
synced 2025-03-14 03:40:25 +08:00
use global mock context parameter
This commit is contained in:
parent
f1edf92626
commit
affa56d057
@ -1,5 +1,6 @@
|
||||
package com.alibaba.testable.agent.handler;
|
||||
|
||||
import com.alibaba.testable.agent.util.ClassUtil;
|
||||
import com.alibaba.testable.core.util.LogUtil;
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
@ -15,30 +16,33 @@ import java.util.Iterator;
|
||||
*/
|
||||
abstract public class BaseClassHandler implements Opcodes {
|
||||
|
||||
protected static final String REF_GET_INSTANCE = "getInstance";
|
||||
protected static final String TESTABLE_REF = "__testable";
|
||||
protected static final String GET_TESTABLE_REF = "testableIns";
|
||||
protected static final String VOID_ARGS = "()";
|
||||
protected static final String VOID_RES = "V";
|
||||
|
||||
protected String mockClassName;
|
||||
|
||||
protected boolean wasTransformed(ClassNode cn, String refName, String refDescriptor) {
|
||||
protected boolean markTransformed(ClassNode cn, String refName, String refDescriptor) {
|
||||
Iterator<FieldNode> iterator = cn.fields.iterator();
|
||||
if (iterator.hasNext()) {
|
||||
if (refName.equals(iterator.next().name)) {
|
||||
// avoid duplicate injection
|
||||
LogUtil.verbose("Duplicate injection found, ignore " + cn.name);
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
cn.fields.add(new FieldNode(ACC_PRIVATE | ACC_STATIC, refName, refDescriptor, null, null));
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public byte[] getBytes(byte[] classFileBuffer) throws IOException {
|
||||
ClassReader cr = new ClassReader(classFileBuffer);
|
||||
ClassNode cn = new ClassNode();
|
||||
cr.accept(cn, 0);
|
||||
transform(cn);
|
||||
if (markTransformed(cn, TESTABLE_REF, ClassUtil.toByteCodeClassName(mockClassName))) {
|
||||
transform(cn);
|
||||
}
|
||||
ClassWriter cw = new ClassWriter( 0);
|
||||
cn.accept(cw);
|
||||
return cw.toByteArray();
|
||||
|
@ -0,0 +1,76 @@
|
||||
package com.alibaba.testable.agent.handler;
|
||||
|
||||
import com.alibaba.testable.agent.util.ClassUtil;
|
||||
import org.objectweb.asm.tree.*;
|
||||
|
||||
/**
|
||||
* @author flin
|
||||
*/
|
||||
abstract public class BaseClassWithContextHandler extends BaseClassHandler {
|
||||
|
||||
private static final String CLASS_TESTABLE_TOOL = "com/alibaba/testable/core/tool/TestableTool";
|
||||
private static final String CLASS_TESTABLE_UTIL = "com/alibaba/testable/core/util/TestableUtil";
|
||||
private static final String CLASS_MOCK_CONTEXT = "com/alibaba/testable/agent/model/MockContext";
|
||||
private static final String FIELD_TEST_CASE = "TEST_CASE";
|
||||
private static final String FIELD_SOURCE_METHOD = "SOURCE_METHOD";
|
||||
private static final String FIELD_MOCK_CONTEXT = "MOCK_CONTEXT";
|
||||
private static final String FIELD_PARAMETERS = "parameters";
|
||||
private static final String METHOD_CURRENT_TEST_CASE_NAME = "currentTestCaseName";
|
||||
private static final String METHOD_CURRENT_SOURCE_METHOD_NAME = "currentSourceMethodName";
|
||||
private static final String METHOD_GET_TEST_CASE_MARK = "getTestCaseMark";
|
||||
private static final String SIGNATURE_CURRENT_TEST_CASE_NAME = "(Ljava/lang/String;)Ljava/lang/String;";
|
||||
private static final String SIGNATURE_CURRENT_SOURCE_METHOD_NAME = "()Ljava/lang/String;";
|
||||
private static final String SIGNATURE_GET_TEST_CASE_MARK = "()Ljava/lang/String;";
|
||||
private static final String SIGNATURE_PARAMETERS = "Ljava/util/Map;";
|
||||
private static final String CLASS_MAP = "java/util/Map";
|
||||
private static final String METHOD_MAP_GET = "get";
|
||||
private static final String SIGNATURE_MAP_GET = "(Ljava/lang/Object;)Ljava/lang/Object;";
|
||||
|
||||
protected AbstractInsnNode[] handleTestableUtil(ClassNode cn, MethodNode mn, AbstractInsnNode[] instructions, int i) {
|
||||
if (instructions[i].getOpcode() == GETSTATIC) {
|
||||
FieldInsnNode fieldInsnNode = (FieldInsnNode)instructions[i];
|
||||
if (isTestableUtilField(fieldInsnNode)) {
|
||||
instructions = replaceTestableUtilField(cn, mn, instructions, fieldInsnNode.name, i);
|
||||
}
|
||||
}
|
||||
return instructions;
|
||||
}
|
||||
|
||||
private boolean isTestableUtilField(FieldInsnNode fieldInsnNode) {
|
||||
return fieldInsnNode.owner.equals(CLASS_TESTABLE_TOOL) &&
|
||||
(fieldInsnNode.name.equals(FIELD_TEST_CASE) || fieldInsnNode.name.equals(FIELD_SOURCE_METHOD) ||
|
||||
fieldInsnNode.name.equals(FIELD_MOCK_CONTEXT));
|
||||
}
|
||||
|
||||
private AbstractInsnNode[] replaceTestableUtilField(ClassNode cn, MethodNode mn, AbstractInsnNode[] instructions,
|
||||
String fieldName, int pos) {
|
||||
InsnList il = new InsnList();
|
||||
if (FIELD_TEST_CASE.equals(fieldName)) {
|
||||
il.add(new LdcInsnNode(ClassUtil.toDotSeparatedName(cn.name)));
|
||||
il.add(new MethodInsnNode(INVOKESTATIC, CLASS_TESTABLE_UTIL, METHOD_CURRENT_TEST_CASE_NAME,
|
||||
SIGNATURE_CURRENT_TEST_CASE_NAME, false));
|
||||
} else if (FIELD_SOURCE_METHOD.equals(fieldName)) {
|
||||
il.add(new MethodInsnNode(INVOKESTATIC, CLASS_TESTABLE_UTIL, METHOD_CURRENT_SOURCE_METHOD_NAME,
|
||||
SIGNATURE_CURRENT_SOURCE_METHOD_NAME, false));
|
||||
} else if (FIELD_MOCK_CONTEXT.equals(fieldName)) {
|
||||
il.add(new FieldInsnNode(GETSTATIC, CLASS_MOCK_CONTEXT, FIELD_PARAMETERS, SIGNATURE_PARAMETERS));
|
||||
il.add(new VarInsnNode(ALOAD, 0));
|
||||
il.add(new MethodInsnNode(INVOKESPECIAL, cn.name, METHOD_GET_TEST_CASE_MARK,
|
||||
SIGNATURE_GET_TEST_CASE_MARK, false));
|
||||
il.add(new MethodInsnNode(INVOKEINTERFACE, CLASS_MAP, METHOD_MAP_GET,
|
||||
SIGNATURE_MAP_GET, true));
|
||||
}
|
||||
if (il.size() > 0) {
|
||||
mn.instructions.insert(instructions[pos], il);
|
||||
mn.instructions.remove(instructions[pos]);
|
||||
}
|
||||
return mn.instructions.toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* get mark compose by TestClass and TestCase
|
||||
* @return test case mark
|
||||
*/
|
||||
abstract protected String getTestCaseMark();
|
||||
|
||||
}
|
@ -4,6 +4,8 @@ import com.alibaba.testable.agent.constant.ConstPool;
|
||||
import com.alibaba.testable.agent.tool.ImmutablePair;
|
||||
import com.alibaba.testable.agent.util.AnnotationUtil;
|
||||
import com.alibaba.testable.agent.util.ClassUtil;
|
||||
import com.alibaba.testable.core.util.InvokeRecordUtil;
|
||||
import com.alibaba.testable.core.util.TestableUtil;
|
||||
import org.objectweb.asm.Type;
|
||||
import org.objectweb.asm.tree.*;
|
||||
|
||||
@ -16,9 +18,8 @@ import static com.alibaba.testable.agent.util.ClassUtil.toDotSeparateFullClassNa
|
||||
/**
|
||||
* @author flin
|
||||
*/
|
||||
public class MockClassHandler extends BaseClassHandler {
|
||||
public class MockClassHandler extends BaseClassWithContextHandler {
|
||||
|
||||
private static final String REF_INSTANCE = "_instance";
|
||||
private static final String CLASS_INVOKE_RECORD_UTIL = "com/alibaba/testable/core/util/InvokeRecordUtil";
|
||||
private static final String METHOD_RECORD_MOCK_INVOKE = "recordMockInvoke";
|
||||
private static final String SIGNATURE_INVOKE_RECORDER_METHOD = "([Ljava/lang/Object;ZZ)V";
|
||||
@ -29,9 +30,6 @@ public class MockClassHandler extends BaseClassHandler {
|
||||
|
||||
@Override
|
||||
protected void transform(ClassNode cn) {
|
||||
if (wasTransformed(cn, REF_INSTANCE, ClassUtil.toByteCodeClassName(mockClassName))) {
|
||||
return;
|
||||
}
|
||||
addGetInstanceMethod(cn);
|
||||
for (MethodNode mn : cn.methods) {
|
||||
if (isMockMethod(mn)) {
|
||||
@ -39,25 +37,41 @@ public class MockClassHandler extends BaseClassHandler {
|
||||
mn.access &= ~ACC_PROTECTED;
|
||||
mn.access |= ACC_PUBLIC;
|
||||
injectInvokeRecorder(mn);
|
||||
handleInstruction(cn, mn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTestCaseMark() {
|
||||
String mockClass = Thread.currentThread().getStackTrace()[InvokeRecordUtil.INDEX_OF_TEST_CLASS].getClassName();
|
||||
// TODO: temporary used
|
||||
String testClass = mockClass.substring(0, mockClass.length() - 5);
|
||||
String testCaseName = TestableUtil.currentTestCaseName(testClass);
|
||||
return testClass + "::" + testCaseName;
|
||||
}
|
||||
|
||||
private void handleInstruction(ClassNode cn, MethodNode mn) {
|
||||
AbstractInsnNode[] instructions = mn.instructions.toArray();
|
||||
for (int i = 0; i < instructions.length; i++) {
|
||||
instructions = handleTestableUtil(cn, mn, instructions, i);
|
||||
}
|
||||
}
|
||||
|
||||
private void addGetInstanceMethod(ClassNode cn) {
|
||||
MethodNode getInstanceMethod = new MethodNode(ACC_PUBLIC | ACC_STATIC, REF_GET_INSTANCE,
|
||||
MethodNode getInstanceMethod = new MethodNode(ACC_PUBLIC | ACC_STATIC, GET_TESTABLE_REF,
|
||||
VOID_ARGS + ClassUtil.toByteCodeClassName(mockClassName), null, null);
|
||||
InsnList il = new InsnList();
|
||||
il.add(new FieldInsnNode(GETSTATIC, mockClassName, REF_INSTANCE,
|
||||
ClassUtil.toByteCodeClassName(mockClassName)));
|
||||
il.add(new FieldInsnNode(GETSTATIC, mockClassName, TESTABLE_REF, ClassUtil.toByteCodeClassName(mockClassName)));
|
||||
LabelNode label = new LabelNode();
|
||||
il.add(new JumpInsnNode(IFNONNULL, label));
|
||||
il.add(new TypeInsnNode(NEW, mockClassName));
|
||||
il.add(new InsnNode(DUP));
|
||||
il.add(new MethodInsnNode(INVOKESPECIAL, mockClassName, CONSTRUCTOR, VOID_ARGS + VOID_RES, false));
|
||||
il.add(new FieldInsnNode(PUTSTATIC, mockClassName, REF_INSTANCE, ClassUtil.toByteCodeClassName(mockClassName)));
|
||||
il.add(new FieldInsnNode(PUTSTATIC, mockClassName, TESTABLE_REF, ClassUtil.toByteCodeClassName(mockClassName)));
|
||||
il.add(label);
|
||||
il.add(new FrameNode(F_SAME, 0, null, 0, null));
|
||||
il.add(new FieldInsnNode(GETSTATIC, mockClassName, REF_INSTANCE, ClassUtil.toByteCodeClassName(mockClassName)));
|
||||
il.add(new FieldInsnNode(GETSTATIC, mockClassName, TESTABLE_REF, ClassUtil.toByteCodeClassName(mockClassName)));
|
||||
il.add(new InsnNode(ARETURN));
|
||||
getInstanceMethod.instructions = il;
|
||||
getInstanceMethod.maxStack = 2;
|
||||
|
@ -20,8 +20,6 @@ import static com.alibaba.testable.agent.constant.ConstPool.CONSTRUCTOR;
|
||||
*/
|
||||
public class SourceClassHandler extends BaseClassHandler {
|
||||
|
||||
private static final String TESTABLE_MARK_FIELD = "__testable";
|
||||
|
||||
private final List<MethodInfo> injectMethods;
|
||||
private final Set<Integer> invokeOps = new HashSet<Integer>() {{
|
||||
add(Opcodes.INVOKEVIRTUAL);
|
||||
@ -41,9 +39,6 @@ public class SourceClassHandler extends BaseClassHandler {
|
||||
*/
|
||||
@Override
|
||||
protected void transform(ClassNode cn) {
|
||||
if (wasTransformed(cn, TESTABLE_MARK_FIELD, ClassUtil.toByteCodeClassName(mockClassName))) {
|
||||
return;
|
||||
}
|
||||
Set<MethodInfo> memberInjectMethods = new HashSet<MethodInfo>();
|
||||
Set<MethodInfo> newOperatorInjectMethods = new HashSet<MethodInfo>();
|
||||
for (MethodInfo im : injectMethods) {
|
||||
@ -209,10 +204,9 @@ public class SourceClassHandler extends BaseClassHandler {
|
||||
newOperatorInjectMethodName);
|
||||
String classType = ((TypeInsnNode)instructions[start]).desc;
|
||||
String constructorDesc = ((MethodInsnNode)instructions[end]).desc;
|
||||
String testClassName = ClassUtil.getTestClassName(cn.name);
|
||||
mn.instructions.insertBefore(instructions[start], new MethodInsnNode(INVOKESTATIC, mockClassName,
|
||||
REF_GET_INSTANCE, VOID_ARGS + ClassUtil.toByteCodeClassName(mockClassName), false));
|
||||
mn.instructions.insertBefore(instructions[end], new MethodInsnNode(INVOKEVIRTUAL, testClassName,
|
||||
GET_TESTABLE_REF, VOID_ARGS + ClassUtil.toByteCodeClassName(mockClassName), false));
|
||||
mn.instructions.insertBefore(instructions[end], new MethodInsnNode(INVOKEVIRTUAL, mockClassName,
|
||||
newOperatorInjectMethodName, getConstructorInjectDesc(constructorDesc, classType), false));
|
||||
mn.instructions.remove(instructions[start]);
|
||||
mn.instructions.remove(instructions[start + 1]);
|
||||
@ -240,9 +234,8 @@ public class SourceClassHandler extends BaseClassHandler {
|
||||
LogUtil.diagnose(" Line %d, mock method \"%s\" used", getLineNum(instructions, start),
|
||||
mockMethod.getMockName());
|
||||
boolean shouldAppendTypeParameter = !mockMethod.getDesc().equals(mockMethod.getMockDesc());
|
||||
String testClassName = ClassUtil.getTestClassName(cn.name);
|
||||
mn.instructions.insertBefore(instructions[start], new MethodInsnNode(INVOKESTATIC, mockClassName,
|
||||
REF_GET_INSTANCE, VOID_ARGS + ClassUtil.toByteCodeClassName(mockClassName), false));
|
||||
GET_TESTABLE_REF, VOID_ARGS + ClassUtil.toByteCodeClassName(mockClassName), false));
|
||||
if (Opcodes.INVOKESTATIC == opcode || isCompanionMethod(ownerClass, opcode)) {
|
||||
if (shouldAppendTypeParameter) {
|
||||
// append a null value if it was a static invoke or in kotlin companion class
|
||||
@ -260,7 +253,7 @@ public class SourceClassHandler extends BaseClassHandler {
|
||||
}
|
||||
}
|
||||
// method with @MockMethod will be modified as public access, so INVOKEVIRTUAL is used
|
||||
mn.instructions.insertBefore(instructions[end], new MethodInsnNode(INVOKEVIRTUAL, testClassName,
|
||||
mn.instructions.insertBefore(instructions[end], new MethodInsnNode(INVOKEVIRTUAL, mockClassName,
|
||||
mockMethod.getMockName(), mockMethod.getMockDesc(), false));
|
||||
mn.instructions.remove(instructions[end]);
|
||||
return new ModifiedInsnNodes(mn.instructions.toArray(), 1);
|
||||
|
@ -1,37 +1,15 @@
|
||||
package com.alibaba.testable.agent.handler;
|
||||
|
||||
import com.alibaba.testable.agent.constant.ConstPool;
|
||||
import com.alibaba.testable.agent.tool.ImmutablePair;
|
||||
import com.alibaba.testable.agent.util.AnnotationUtil;
|
||||
import com.alibaba.testable.agent.util.ClassUtil;
|
||||
import com.alibaba.testable.core.util.LogUtil;
|
||||
import org.objectweb.asm.Type;
|
||||
import org.objectweb.asm.tree.*;
|
||||
|
||||
import javax.lang.model.type.NullType;
|
||||
import java.util.List;
|
||||
|
||||
import static com.alibaba.testable.agent.constant.ConstPool.CONSTRUCTOR;
|
||||
import static com.alibaba.testable.agent.util.ClassUtil.toDotSeparateFullClassName;
|
||||
import com.alibaba.testable.core.util.InvokeRecordUtil;
|
||||
import com.alibaba.testable.core.util.TestableUtil;
|
||||
import org.objectweb.asm.tree.AbstractInsnNode;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.objectweb.asm.tree.MethodNode;
|
||||
|
||||
/**
|
||||
* @author flin
|
||||
*/
|
||||
public class TestClassHandler extends BaseClassHandler {
|
||||
|
||||
private static final String CLASS_TESTABLE_TOOL = "com/alibaba/testable/core/tool/TestableTool";
|
||||
private static final String CLASS_TESTABLE_UTIL = "com/alibaba/testable/core/util/TestableUtil";
|
||||
private static final String CLASS_MOCK_CONTEXT = "com/alibaba/testable/agent/model/MockContext";
|
||||
private static final String REF_TESTABLE_CONTEXT = "_testableContextReference";
|
||||
private static final String FIELD_TEST_CASE = "TEST_CASE";
|
||||
private static final String FIELD_SOURCE_METHOD = "SOURCE_METHOD";
|
||||
private static final String FIELD_MOCK_CONTEXT = "MOCK_CONTEXT";
|
||||
private static final String FIELD_PARAMETERS = "parameters";
|
||||
private static final String METHOD_CURRENT_TEST_CASE_NAME = "currentTestCaseName";
|
||||
private static final String METHOD_CURRENT_SOURCE_METHOD_NAME = "currentSourceMethodName";
|
||||
private static final String SIGNATURE_CURRENT_TEST_CASE_NAME = "(Ljava/lang/String;)Ljava/lang/String;";
|
||||
private static final String SIGNATURE_CURRENT_SOURCE_METHOD_NAME = "()Ljava/lang/String;";
|
||||
private static final String SIGNATURE_PARAMETERS = "Ljava/util/Map;";
|
||||
public class TestClassHandler extends BaseClassWithContextHandler {
|
||||
|
||||
public TestClassHandler(String mockClassName) {
|
||||
this.mockClassName = mockClassName;
|
||||
@ -43,69 +21,23 @@ public class TestClassHandler extends BaseClassHandler {
|
||||
*/
|
||||
@Override
|
||||
protected void transform(ClassNode cn) {
|
||||
if (wasTransformed(cn, REF_TESTABLE_CONTEXT, ClassUtil.toByteCodeClassName(mockClassName))) {
|
||||
return;
|
||||
}
|
||||
for (MethodNode mn : cn.methods) {
|
||||
if (mn.name.equals(ConstPool.CONSTRUCTOR)) {
|
||||
initMockContextReference(cn, mn);
|
||||
} else {
|
||||
handleInstruction(cn, mn);
|
||||
}
|
||||
handleInstruction(cn, mn);
|
||||
}
|
||||
}
|
||||
|
||||
private void initMockContextReference(ClassNode cn, MethodNode mn) {
|
||||
InsnList il = new InsnList();
|
||||
il.add(new TypeInsnNode(NEW, CLASS_MOCK_CONTEXT));
|
||||
il.add(new InsnNode(DUP));
|
||||
il.add(new MethodInsnNode(INVOKESPECIAL, CLASS_MOCK_CONTEXT, CONSTRUCTOR, "()V", false));
|
||||
il.add(new FieldInsnNode(PUTSTATIC, cn.name, REF_TESTABLE_CONTEXT,
|
||||
ClassUtil.toByteCodeClassName(CLASS_MOCK_CONTEXT)));
|
||||
mn.instructions.insertBefore(mn.instructions.get(0), il);
|
||||
mn.maxStack++;
|
||||
@Override
|
||||
protected String getTestCaseMark() {
|
||||
String testClass = Thread.currentThread().getStackTrace()[InvokeRecordUtil.INDEX_OF_TEST_CLASS].getClassName();
|
||||
String testCaseName = TestableUtil.currentTestCaseName(testClass);
|
||||
return testClass + "::" + testCaseName;
|
||||
}
|
||||
|
||||
private void handleInstruction(ClassNode cn, MethodNode mn) {
|
||||
AbstractInsnNode[] instructions = mn.instructions.toArray();
|
||||
int i = 0;
|
||||
do {
|
||||
if (instructions[i].getOpcode() == GETSTATIC) {
|
||||
FieldInsnNode fieldInsnNode = (FieldInsnNode)instructions[i];
|
||||
if (isTestableUtilField(fieldInsnNode)) {
|
||||
instructions = replaceTestableUtilField(cn, mn, instructions, fieldInsnNode.name, i);
|
||||
}
|
||||
}
|
||||
i++;
|
||||
} while (i < instructions.length);
|
||||
}
|
||||
|
||||
private boolean isTestableUtilField(FieldInsnNode fieldInsnNode) {
|
||||
return fieldInsnNode.owner.equals(CLASS_TESTABLE_TOOL) &&
|
||||
(fieldInsnNode.name.equals(FIELD_TEST_CASE) || fieldInsnNode.name.equals(FIELD_SOURCE_METHOD) ||
|
||||
fieldInsnNode.name.equals(FIELD_MOCK_CONTEXT));
|
||||
}
|
||||
|
||||
private AbstractInsnNode[] replaceTestableUtilField(ClassNode cn, MethodNode mn, AbstractInsnNode[] instructions,
|
||||
String fieldName, int pos) {
|
||||
InsnList il = new InsnList();
|
||||
if (FIELD_TEST_CASE.equals(fieldName)) {
|
||||
il.add(new LdcInsnNode(ClassUtil.toDotSeparatedName(cn.name)));
|
||||
il.add(new MethodInsnNode(INVOKESTATIC, CLASS_TESTABLE_UTIL, METHOD_CURRENT_TEST_CASE_NAME,
|
||||
SIGNATURE_CURRENT_TEST_CASE_NAME, false));
|
||||
} else if (FIELD_SOURCE_METHOD.equals(fieldName)) {
|
||||
il.add(new MethodInsnNode(INVOKESTATIC, CLASS_TESTABLE_UTIL, METHOD_CURRENT_SOURCE_METHOD_NAME,
|
||||
SIGNATURE_CURRENT_SOURCE_METHOD_NAME, false));
|
||||
} else if (FIELD_MOCK_CONTEXT.equals(fieldName)) {
|
||||
il.add(new FieldInsnNode(GETSTATIC, cn.name, REF_TESTABLE_CONTEXT,
|
||||
ClassUtil.toByteCodeClassName(CLASS_MOCK_CONTEXT)));
|
||||
il.add(new FieldInsnNode(GETFIELD, CLASS_MOCK_CONTEXT, FIELD_PARAMETERS, SIGNATURE_PARAMETERS));
|
||||
for (int i = 0; i < instructions.length; i++) {
|
||||
instructions = handleTestableUtil(cn, mn, instructions, i);
|
||||
}
|
||||
if (il.size() > 0) {
|
||||
mn.instructions.insert(instructions[pos], il);
|
||||
mn.instructions.remove(instructions[pos]);
|
||||
}
|
||||
return mn.instructions.toArray();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -8,6 +8,9 @@ import java.util.Map;
|
||||
*/
|
||||
public class MockContext {
|
||||
|
||||
public Map<String, Object> parameters = new HashMap<String, Object>();
|
||||
/**
|
||||
* Mock method name → ( key → value )
|
||||
*/
|
||||
public static final Map<String, Map<String, Object>> parameters = new HashMap<String, Map<String, Object>>();
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user