mirror of
https://github.com/alibaba/testable-mock.git
synced 2025-01-09 11:50:40 +08:00
support mock package mapping
This commit is contained in:
parent
a33908db41
commit
c577301493
@ -22,6 +22,7 @@ public class PropertiesParser {
|
||||
private static final String LOG_FILE = "log.file";
|
||||
private static final String LOG_LEVEL = "log.level";
|
||||
private static final String INNER_MOCK_CLASS_NAME = "mock.innerClass.name";
|
||||
private static final String MOCK_PKG_MAPPING_PREFIX = "mock.package.mapping.";
|
||||
private static final String DEFAULT_MOCK_SCOPE = "mock.scope.default";
|
||||
private static final String ENABLE_OMNI_INJECT = "omni.constructor.enhance.enable";
|
||||
private static final String OMNI_INJECT_EXCLUDES = "omni.constructor.enhance.pkgPrefix.excludes";
|
||||
@ -62,6 +63,8 @@ public class PropertiesParser {
|
||||
GlobalConfig.setLogLevel(v);
|
||||
} else if (k.equals(INNER_MOCK_CLASS_NAME)) {
|
||||
GlobalConfig.setInnerMockClassName(v);
|
||||
} else if (k.startsWith(MOCK_PKG_MAPPING_PREFIX)) {
|
||||
GlobalConfig.addMockPackageMapping(k.substring(MOCK_PKG_MAPPING_PREFIX.length()), v);
|
||||
} else if (k.equals(DEFAULT_MOCK_SCOPE)) {
|
||||
GlobalConfig.setDefaultMockScope(MockScope.of(v));
|
||||
} else if (k.equals(ENABLE_OMNI_INJECT)) {
|
||||
|
@ -21,7 +21,6 @@ import java.security.ProtectionDomain;
|
||||
import java.util.List;
|
||||
|
||||
import static com.alibaba.testable.agent.constant.ConstPool.*;
|
||||
import static com.alibaba.testable.agent.util.ClassUtil.toJavaStyleClassName;
|
||||
import static com.alibaba.testable.core.constant.ConstPool.DOLLAR;
|
||||
import static com.alibaba.testable.core.constant.ConstPool.TEST_POSTFIX;
|
||||
import static com.alibaba.testable.core.util.PathUtil.createFolder;
|
||||
@ -67,29 +66,26 @@ public class TestableClassTransformer implements ClassFileTransformer {
|
||||
}
|
||||
|
||||
private byte[] transformMock(byte[] bytes, ClassNode cn) {
|
||||
String className = cn.name;
|
||||
String className = (GlobalConfig.getMockPackageMapping() == null) ? cn.name : mapPackage(cn.name);
|
||||
try {
|
||||
if (mockClassParser.isMockClass(cn)) {
|
||||
// it's a mock class
|
||||
LogUtil.diagnose("Found mock class %s", className);
|
||||
bytes = new MockClassHandler(className).getBytes(bytes);
|
||||
BytecodeUtil.dumpByte(className, GlobalConfig.getDumpPath(), bytes);
|
||||
} else if (foundMockForTestClass(className) != null) {
|
||||
// it's a test class with testable enabled
|
||||
LogUtil.diagnose("Found test class %s", className);
|
||||
bytes = new TestClassHandler().getBytes(bytes);
|
||||
BytecodeUtil.dumpByte(className, GlobalConfig.getDumpPath(), bytes);
|
||||
} else {
|
||||
String mockClass = foundMockForTestClass(className);
|
||||
String mockClass = foundMockForSourceClass(className);
|
||||
if (mockClass != null) {
|
||||
// it's a test class with testable enabled
|
||||
LogUtil.diagnose("Found test class %s", className);
|
||||
bytes = new TestClassHandler().getBytes(bytes);
|
||||
// it's a source class with testable enabled
|
||||
List<MethodInfo> injectMethods = mockClassParser.getTestableMockMethods(mockClass);
|
||||
LogUtil.diagnose("Found source class %s", className);
|
||||
bytes = new SourceClassHandler(injectMethods, mockClass).getBytes(bytes);
|
||||
BytecodeUtil.dumpByte(className, GlobalConfig.getDumpPath(), bytes);
|
||||
} else {
|
||||
mockClass = foundMockForSourceClass(className);
|
||||
if (mockClass != null) {
|
||||
// it's a source class with testable enabled
|
||||
List<MethodInfo> injectMethods = mockClassParser.getTestableMockMethods(mockClass);
|
||||
LogUtil.diagnose("Found source class %s", className);
|
||||
bytes = new SourceClassHandler(injectMethods, mockClass).getBytes(bytes);
|
||||
BytecodeUtil.dumpByte(className, GlobalConfig.getDumpPath(), bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
@ -103,6 +99,17 @@ public class TestableClassTransformer implements ClassFileTransformer {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
private String mapPackage(String name) {
|
||||
String dotSeparatedName = ClassUtil.toDotSeparatedName(name);
|
||||
for (String prefix : GlobalConfig.getMockPackageMapping().keySet()) {
|
||||
if (dotSeparatedName.startsWith(prefix)) {
|
||||
return ClassUtil.toSlashSeparatedName(GlobalConfig.getMockPackageMapping().get(prefix))
|
||||
+ name.substring(prefix.length());
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
private String foundMockForSourceClass(String className) {
|
||||
String mockClass = lookForMockWithAnnotationAsSourceClass(className);
|
||||
if (mockClass != null) {
|
||||
@ -236,7 +243,7 @@ public class TestableClassTransformer implements ClassFileTransformer {
|
||||
private String parseMockWithAnnotation(ClassNode cn, ClassType expectedType) {
|
||||
if (cn.visibleAnnotations != null) {
|
||||
for (AnnotationNode an : cn.visibleAnnotations) {
|
||||
if (toJavaStyleClassName(an.desc).equals(ConstPool.MOCK_WITH)) {
|
||||
if (ClassUtil.toJavaStyleClassName(an.desc).equals(ConstPool.MOCK_WITH)) {
|
||||
ClassType type = AnnotationUtil.getAnnotationParameter(an, FIELD_TREAT_AS, ClassType.GuessByName,
|
||||
ClassType.class);
|
||||
if (isExpectedType(cn.name, type, expectedType)) {
|
||||
@ -254,7 +261,7 @@ public class TestableClassTransformer implements ClassFileTransformer {
|
||||
private String getDumpPathByAnnotation(ClassNode cn) {
|
||||
if (cn.visibleAnnotations != null) {
|
||||
for (AnnotationNode an : cn.visibleAnnotations) {
|
||||
if (toJavaStyleClassName(an.desc).equals(ConstPool.DUMP_TO)) {
|
||||
if (ClassUtil.toJavaStyleClassName(an.desc).equals(ConstPool.DUMP_TO)) {
|
||||
String path = AnnotationUtil.getAnnotationParameter(an, FIELD_VALUE, null, String.class);
|
||||
String fullPath = PathUtil.join(System.getProperty(PROPERTY_USER_DIR), path);
|
||||
if (createFolder(fullPath)) {
|
||||
|
@ -7,12 +7,13 @@ import com.alibaba.testable.core.util.LogUtil;
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.alibaba.testable.agent.constant.ConstPool.PROPERTY_TEMP_DIR;
|
||||
import static com.alibaba.testable.agent.constant.ConstPool.PROPERTY_USER_DIR;
|
||||
import static com.alibaba.testable.core.constant.ConstPool.COMMA;
|
||||
import static com.alibaba.testable.core.constant.ConstPool.DOT;
|
||||
import static com.alibaba.testable.core.constant.ConstPool.*;
|
||||
import static com.alibaba.testable.core.util.PathUtil.createFolder;
|
||||
|
||||
/**
|
||||
@ -36,6 +37,7 @@ public class GlobalConfig {
|
||||
private static boolean enhanceThreadLocal = false;
|
||||
private static boolean enhanceOmniConstructor = false;
|
||||
private static String innerMockClassName = "Mock";
|
||||
private static Map<String, String> mockPkgMapping = null;
|
||||
|
||||
public static void setLogLevel(String level) {
|
||||
if (level.equals(MUTE)) {
|
||||
@ -103,7 +105,7 @@ public class GlobalConfig {
|
||||
|
||||
private static String getBuildOutputFolder() {
|
||||
String contextFolder = System.getProperty(PROPERTY_USER_DIR);
|
||||
URL rootResourceFolder = Object.class.getResource("/");
|
||||
URL rootResourceFolder = Object.class.getResource(SLASH);
|
||||
if (rootResourceFolder != null) {
|
||||
return PathUtil.getFirstLevelFolder(contextFolder, rootResourceFolder.getPath());
|
||||
} else if (PathUtil.folderExists(PathUtil.join(contextFolder, DEFAULT_MAVEN_OUTPUT_FOLDER))) {
|
||||
@ -139,6 +141,17 @@ public class GlobalConfig {
|
||||
return innerMockClassName;
|
||||
}
|
||||
|
||||
public static void addMockPackageMapping(String originPkg, String mockClassPkg) {
|
||||
if (mockPkgMapping == null) {
|
||||
mockPkgMapping = new HashMap<String, String>(5);
|
||||
}
|
||||
mockPkgMapping.put(originPkg + DOT, mockClassPkg + DOT);
|
||||
}
|
||||
|
||||
public static Map<String, String> getMockPackageMapping() {
|
||||
return mockPkgMapping;
|
||||
}
|
||||
|
||||
private static List<String> parsePkgPrefixList(String prefixes) {
|
||||
List<String> whiteList = new ArrayList<String>();
|
||||
for (String p : prefixes.split(COMMA)) {
|
||||
|
@ -177,7 +177,6 @@ public class OmniConstructor {
|
||||
// don't travel null object
|
||||
return;
|
||||
}
|
||||
LogUtil.verbose(classPool.size(), "Verifying %s", type.getName());
|
||||
classPool.put(type, instance);
|
||||
for (Field f : TypeUtil.getAllFields(type)) {
|
||||
if (f.getName().startsWith("$") || isStaticFinalField(f)) {
|
||||
@ -190,14 +189,14 @@ public class OmniConstructor {
|
||||
if (fieldType.isArray()) {
|
||||
Class<?> componentType = fieldType.getComponentType();
|
||||
if (fieldIns != null && !TypeUtil.isBasicType(componentType)) {
|
||||
LogUtil.verbose(classPool.size(), "Field(Array[%d]) %s", Array.getLength(fieldIns), f.getName());
|
||||
LogUtil.verbose(classPool.size(), "Verifying Field(Array[%d]) %s", Array.getLength(fieldIns), f.getName());
|
||||
handleCircleReferenceOfArrayField(fieldIns, componentType, classPool);
|
||||
}
|
||||
} else if (!TypeUtil.isBasicType(fieldType)) {
|
||||
if (fieldIns == null && classPool.containsKey(fieldType)) {
|
||||
f.set(instance, classPool.get(fieldType));
|
||||
} else if (!classPool.containsKey(fieldType)) {
|
||||
LogUtil.verbose(classPool.size(), "Field %s", f.getName());
|
||||
LogUtil.verbose(classPool.size(), "Verifying Field %s", f.getName());
|
||||
handleCircleReference(fieldIns, fieldType, classPool);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user