mirror of
https://github.com/alibaba/testable-mock.git
synced 2025-01-25 20:00:17 +08:00
use mock class to setup diagnose
This commit is contained in:
parent
65cc631d39
commit
82d87f3447
@ -94,7 +94,7 @@ public class MockClassHandler extends BaseClassWithContextHandler {
|
||||
// must get label before method description changed
|
||||
ImmutablePair<LabelNode, LabelNode> labels = getStartAndEndLabel(mn);
|
||||
mn.desc = MethodUtil.addParameterAtBegin(mn.desc, targetClassName);
|
||||
int parameterOffset = MethodUtil.isStaticMethod(mn) ? 0 : 1;
|
||||
int parameterOffset = MethodUtil.isStatic(mn) ? 0 : 1;
|
||||
mn.localVariables.add(parameterOffset, new LocalVariableNode("__self", targetClassName, null,
|
||||
labels.left, labels.right, parameterOffset));
|
||||
for (int i = parameterOffset + 1; i < mn.localVariables.size(); i++) {
|
||||
@ -114,7 +114,7 @@ public class MockClassHandler extends BaseClassWithContextHandler {
|
||||
}
|
||||
|
||||
private ImmutablePair<LabelNode, LabelNode> getStartAndEndLabel(MethodNode mn) {
|
||||
if (MethodUtil.isStaticMethod(mn)) {
|
||||
if (MethodUtil.isStatic(mn)) {
|
||||
LabelNode startLabel = null, endLabel = null;
|
||||
for (AbstractInsnNode n = mn.instructions.getFirst(); n != null; n = n.getNext()) {
|
||||
if (n instanceof LabelNode) {
|
||||
@ -251,7 +251,7 @@ public class MockClassHandler extends BaseClassWithContextHandler {
|
||||
int size = types.size();
|
||||
il.add(getIntInsn(size));
|
||||
il.add(new TypeInsnNode(ANEWARRAY, ClassUtil.CLASS_OBJECT));
|
||||
int parameterOffset = MethodUtil.isStaticMethod(mn) ? 0 : 1;
|
||||
int parameterOffset = MethodUtil.isStatic(mn) ? 0 : 1;
|
||||
for (int i = 0; i < size; i++) {
|
||||
il.add(new InsnNode(DUP));
|
||||
il.add(getIntInsn(i));
|
||||
|
@ -22,6 +22,8 @@ public class TestClassHandler extends BaseClassWithContextHandler {
|
||||
private static final String DESC_METHOD_CLEAN = "()V";
|
||||
private static final String THIS = "this";
|
||||
|
||||
private int testCaseCount = 0;
|
||||
|
||||
private final Framework[] frameworkClasses = new Framework[] {
|
||||
new JUnit4Framework(),
|
||||
new JUnit5Framework(),
|
||||
@ -51,6 +53,7 @@ public class TestClassHandler extends BaseClassWithContextHandler {
|
||||
handleTestableUtil(mn);
|
||||
handleTestCaseMethod(mn, framework);
|
||||
}
|
||||
LogUtil.diagnose(String.format(" Found %d test cases", testCaseCount));
|
||||
}
|
||||
|
||||
private Framework checkFramework(ClassNode cn) {
|
||||
@ -96,7 +99,9 @@ public class TestClassHandler extends BaseClassWithContextHandler {
|
||||
private void handleTestCaseMethod(MethodNode mn, Framework framework) {
|
||||
TestCaseMethodType type = framework.checkMethodType(mn);
|
||||
if (type.equals(TestCaseMethodType.TEST)) {
|
||||
LogUtil.verbose(String.format(" Test case \"%s\"", mn.name));
|
||||
injectMockContextInit(mn);
|
||||
testCaseCount++;
|
||||
} else if (type.equals(TestCaseMethodType.AFTER_TEST)) {
|
||||
injectMockContextClean(mn);
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ import com.alibaba.testable.agent.util.ClassUtil;
|
||||
import com.alibaba.testable.agent.util.DiagnoseUtil;
|
||||
import com.alibaba.testable.agent.util.MethodUtil;
|
||||
import com.alibaba.testable.core.util.LogUtil;
|
||||
import com.alibaba.testable.core.util.MockAssociationUtil;
|
||||
import org.objectweb.asm.Type;
|
||||
import org.objectweb.asm.tree.AnnotationNode;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
@ -18,7 +17,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static com.alibaba.testable.agent.util.ClassUtil.toDotSeparateFullClassName;
|
||||
import static com.alibaba.testable.agent.util.MethodUtil.isStaticMethod;
|
||||
import static com.alibaba.testable.agent.util.MethodUtil.isStatic;
|
||||
import static com.alibaba.testable.core.constant.ConstPool.CONSTRUCTOR;
|
||||
|
||||
public class MockClassParser {
|
||||
@ -50,11 +49,6 @@ public class MockClassParser {
|
||||
* @return found annotation or not
|
||||
*/
|
||||
public boolean isMockClass(String className) {
|
||||
return MockAssociationUtil.mockToTests.containsKey(ClassUtil.toDotSeparatedName(className)) ||
|
||||
hasMockMethod(className);
|
||||
}
|
||||
|
||||
private boolean hasMockMethod(String className) {
|
||||
ClassNode cn = ClassUtil.getClassNode(className);
|
||||
if (cn == null) {
|
||||
return false;
|
||||
@ -120,7 +114,7 @@ public class MockClassParser {
|
||||
|
||||
private MethodInfo getMethodInfo(MethodNode mn, AnnotationNode an, String targetMethod) {
|
||||
Type targetType = AnnotationUtil.getAnnotationParameter(an, ConstPool.FIELD_TARGET_CLASS, null, Type.class);
|
||||
boolean isStatic = isStaticMethod(mn);
|
||||
boolean isStatic = isStatic(mn);
|
||||
if (targetType == null) {
|
||||
// "targetClass" unset, use first parameter as target class type
|
||||
ImmutablePair<String, String> methodDescPair = extractFirstParameter(mn.desc);
|
||||
@ -138,7 +132,7 @@ public class MockClassParser {
|
||||
|
||||
private void addMockConstructor(List<MethodInfo> methodInfos, ClassNode cn, MethodNode mn) {
|
||||
String sourceClassName = ClassUtil.getSourceClassName(cn.name);
|
||||
methodInfos.add(new MethodInfo(sourceClassName, CONSTRUCTOR, mn.desc, mn.name, mn.desc, isStaticMethod(mn)));
|
||||
methodInfos.add(new MethodInfo(sourceClassName, CONSTRUCTOR, mn.desc, mn.name, mn.desc, isStatic(mn)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -106,7 +106,7 @@ public class TestableClassTransformer implements ClassFileTransformer {
|
||||
}
|
||||
|
||||
private String foundMockForSourceClass(String className) {
|
||||
String mockClass = readMockWithAnnotationAsSourceClass(className);
|
||||
String mockClass = lookForMockWithAnnotationAsSourceClass(className);
|
||||
if (mockClass != null) {
|
||||
return mockClass;
|
||||
}
|
||||
@ -114,10 +114,23 @@ public class TestableClassTransformer implements ClassFileTransformer {
|
||||
}
|
||||
|
||||
private String foundMockForTestClass(String className) {
|
||||
String mockClass = readMockWithAnnotationAndInnerClassAsTestClass(className);
|
||||
ClassNode cn = ClassUtil.getClassNode(className);
|
||||
if (cn == null) {
|
||||
return null;
|
||||
}
|
||||
String mockClass = lookForMockWithAnnotationAsTestClass(cn);
|
||||
if (mockClass != null) {
|
||||
return mockClass;
|
||||
}
|
||||
mockClass = lookForInnerMockClass(cn);
|
||||
if (mockClass != null) {
|
||||
return mockClass;
|
||||
}
|
||||
return lookForOuterMockClass(className);
|
||||
}
|
||||
|
||||
private String lookForOuterMockClass(String className) {
|
||||
String mockClass;
|
||||
mockClass = ClassUtil.getMockClassName(ClassUtil.getSourceClassName(className));
|
||||
if (mockClassParser.isMockClass(mockClass)) {
|
||||
return mockClass;
|
||||
@ -160,7 +173,7 @@ public class TestableClassTransformer implements ClassFileTransformer {
|
||||
* @param className class that need to explore
|
||||
* @return name of mock class, null for not found
|
||||
*/
|
||||
private String readMockWithAnnotationAsSourceClass(String className) {
|
||||
private String lookForMockWithAnnotationAsSourceClass(String className) {
|
||||
ClassNode cn = ClassUtil.getClassNode(className);
|
||||
if (cn == null) {
|
||||
return null;
|
||||
@ -169,35 +182,40 @@ public class TestableClassTransformer implements ClassFileTransformer {
|
||||
}
|
||||
|
||||
/**
|
||||
* Read @MockWith annotation upon class and inner class "Mock" to fetch mock class
|
||||
* Read inner class "Mock" to fetch mock class
|
||||
*
|
||||
* @param className class that need to explore
|
||||
* @param cn class that need to explore
|
||||
* @return name of mock class, null for not found
|
||||
*/
|
||||
private String readMockWithAnnotationAndInnerClassAsTestClass(String className) {
|
||||
ClassNode cn = ClassUtil.getClassNode(className);
|
||||
if (cn == null) {
|
||||
return null;
|
||||
}
|
||||
// look for MockWith annotation
|
||||
String mockClassName = parseMockWithAnnotation(cn, ClassType.TestClass);
|
||||
if (mockClassName != null) {
|
||||
MockAssociationUtil.mockToTests.get(mockClassName).add(ClassUtil.toDotSeparateFullClassName(className));
|
||||
return ClassUtil.toSlashSeparatedName(mockClassName);
|
||||
}
|
||||
// look for Mock inner class
|
||||
private String lookForInnerMockClass(ClassNode cn) {
|
||||
for (InnerClassNode ic : cn.innerClasses) {
|
||||
if ((ic.access & ACC_PUBLIC) != 0 && ic.name.equals(getInnerMockClassName(className))) {
|
||||
if ((ic.access & ACC_PUBLIC) != 0 && ic.name.equals(getInnerMockClassName(cn.name)) &&
|
||||
mockClassParser.isMockClass(ic.name)) {
|
||||
if ((ic.access & ACC_STATIC) != 0) {
|
||||
return ic.name;
|
||||
} else {
|
||||
LogUtil.warn(String.format("Mock class in \"%s\" is not static", className));
|
||||
LogUtil.warn(String.format("Mock class in \"%s\" is not declared as static", cn.name));
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read @MockWith annotation upon class to fetch mock class
|
||||
*
|
||||
* @param cn class that need to explore
|
||||
* @return name of mock class, null for not found
|
||||
*/
|
||||
private String lookForMockWithAnnotationAsTestClass(ClassNode cn) {
|
||||
String mockClassName = parseMockWithAnnotation(cn, ClassType.TestClass);
|
||||
if (mockClassName != null) {
|
||||
MockAssociationUtil.mockToTests.get(mockClassName).add(ClassUtil.toDotSeparateFullClassName(cn.name));
|
||||
return ClassUtil.toSlashSeparatedName(mockClassName);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get mock class from @MockWith annotation
|
||||
*
|
||||
|
@ -15,7 +15,7 @@ public class MethodUtil {
|
||||
* @param mn method to check
|
||||
* @return is static or not
|
||||
*/
|
||||
public static boolean isStaticMethod(MethodNode mn) {
|
||||
public static boolean isStatic(MethodNode mn) {
|
||||
return (mn.access & ACC_STATIC) != 0;
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,7 @@ public @interface MockWith {
|
||||
|
||||
/**
|
||||
* explicitly specify mock class
|
||||
* @note this parameter will become mandatory in v0.6
|
||||
* @return type of mock class
|
||||
*/
|
||||
Class<?> value() default NullType.class;
|
||||
|
@ -46,7 +46,7 @@ public class LogUtil {
|
||||
|
||||
public static void warn(String msg, Object... args) {
|
||||
if (currentLogLevel.level >= LogLevel.LEVEL_WARN.level) {
|
||||
System.out.println(String.format("[WARN] " + msg, args));
|
||||
System.err.println(String.format("[WARN] " + msg, args));
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user