diff --git a/testable-agent/src/main/java/com/alibaba/testable/agent/transformer/TestableClassTransformer.java b/testable-agent/src/main/java/com/alibaba/testable/agent/transformer/TestableClassTransformer.java index 49b2ab8..0093e29 100644 --- a/testable-agent/src/main/java/com/alibaba/testable/agent/transformer/TestableClassTransformer.java +++ b/testable-agent/src/main/java/com/alibaba/testable/agent/transformer/TestableClassTransformer.java @@ -34,6 +34,7 @@ public class TestableClassTransformer implements ClassFileTransformer { private static final String FIELD_VALUE = "value"; private static final String FIELD_TREAT_AS = "treatAs"; + private static final String CLASS_JUNIT_5_NESTED = "Lorg/junit/jupiter/api/Nested;"; /** * Just avoid spend time to scan those surely non-user classes, should keep these lists as tiny as possible @@ -119,7 +120,7 @@ public class TestableClassTransformer implements ClassFileTransformer { } private String foundMockForTestClass(String className) { - ClassNode cn = ClassUtil.getClassNode(className); + ClassNode cn = adaptInnerClass(ClassUtil.getClassNode(className)); if (cn != null) { String mockClass = lookForMockWithAnnotationAsTestClass(cn); if (mockClass != null) { @@ -133,6 +134,18 @@ public class TestableClassTransformer implements ClassFileTransformer { return lookForOuterMockClass(className); } + private ClassNode adaptInnerClass(ClassNode cn) { + if (cn == null || cn.visibleAnnotations == null) { + return cn; + } + for (AnnotationNode an : cn.visibleAnnotations) { + if (an.desc.equals(CLASS_JUNIT_5_NESTED)) { + return ClassUtil.getClassNode(ClassUtil.toOuterClassName(cn.name)); + } + } + return cn; + } + private String lookForOuterMockClass(String className) { String mockClassName = ClassUtil.getMockClassName(ClassUtil.getSourceClassName(className)); if (mockClassParser.isMockClass(ClassUtil.getClassNode(mockClassName))) { diff --git a/testable-agent/src/main/java/com/alibaba/testable/agent/util/ClassUtil.java b/testable-agent/src/main/java/com/alibaba/testable/agent/util/ClassUtil.java index 1b53ca2..96b140a 100644 --- a/testable-agent/src/main/java/com/alibaba/testable/agent/util/ClassUtil.java +++ b/testable-agent/src/main/java/com/alibaba/testable/agent/util/ClassUtil.java @@ -234,8 +234,17 @@ public class ClassUtil { return cn; } + /** + * Get outer class name from a inner class name + * @param name inner class name + * @return outer class name + */ + public static String toOuterClassName(String name) { + int pos = name.lastIndexOf("$"); + return (pos > 0) ? name.substring(0, pos) : name; + } + private static String toDescriptor(Byte type, String objectType) { return "(" + (char)type.byteValue() + ")L" + objectType + ";"; } - } diff --git a/testable-agent/src/test/java/com/alibaba/testable/agent/util/ClassUtilTest.java b/testable-agent/src/test/java/com/alibaba/testable/agent/util/ClassUtilTest.java index 4804486..200f519 100644 --- a/testable-agent/src/test/java/com/alibaba/testable/agent/util/ClassUtilTest.java +++ b/testable-agent/src/test/java/com/alibaba/testable/agent/util/ClassUtilTest.java @@ -23,5 +23,13 @@ class ClassUtilTest { ClassUtil.fitCompanionClassName("com/alibaba/testable/demo/BlackBox$Companion")); } + @Test + void should_get_outer_class_name() { + assertEquals("com/alibaba/demo/basic/DemoMockTest", + ClassUtil.toOuterClassName("com/alibaba/demo/basic/DemoMockTest$Inner")); + assertEquals("com/alibaba/demo/basic/DemoMockTest", + ClassUtil.toOuterClassName("com/alibaba/demo/basic/DemoMockTest")); + } + }