diff --git a/demo/java-demo/src/test/java/com/alibaba/testable/demo/DemoServiceTest.java b/demo/java-demo/src/test/java/com/alibaba/testable/demo/DemoServiceTest.java index ee604e0..ca83029 100644 --- a/demo/java-demo/src/test/java/com/alibaba/testable/demo/DemoServiceTest.java +++ b/demo/java-demo/src/test/java/com/alibaba/testable/demo/DemoServiceTest.java @@ -1,46 +1,45 @@ package com.alibaba.testable.demo; import com.alibaba.testable.core.accessor.PrivateAccessor; -import com.alibaba.testable.core.annotation.EnableTestable; -import com.alibaba.testable.core.annotation.TestableInject; +import com.alibaba.testable.core.annotation.EnablePrivateAccess; +import com.alibaba.testable.core.annotation.TestableMock; import org.junit.jupiter.api.Test; -import java.util.concurrent.Callable; import java.util.concurrent.Executors; import static com.alibaba.testable.core.tool.TestableTool.SOURCE_METHOD; import static com.alibaba.testable.core.tool.TestableTool.TEST_CASE; import static org.junit.jupiter.api.Assertions.assertEquals; -@EnableTestable +@EnablePrivateAccess class DemoServiceTest { - @TestableInject + @TestableMock private BlackBox createBlackBox(String text) { return new BlackBox("mock_" + text); } - @TestableInject + @TestableMock private String innerFunc(String text) { return "mock_" + text; } - @TestableInject(targetClass = String.class) + @TestableMock(targetClass = String.class) private String trim(String self) { return "trim_string"; } - @TestableInject(targetClass = String.class, targetMethod = "substring") + @TestableMock(targetClass = String.class, targetMethod = "substring") private String sub(String self, int i, int j) { return "sub_string"; } - @TestableInject(targetClass = String.class) + @TestableMock(targetClass = String.class) private boolean startsWith(String self, String s) { return false; } - @TestableInject + @TestableMock private String callFromDifferentMethod() { if (TEST_CASE.equals("should_able_to_get_test_case_name")) { return "mock_special"; diff --git a/demo/kotlin-demo/src/test/kotlin/com/alibaba/testable/demo/DemoServiceTest.kt b/demo/kotlin-demo/src/test/kotlin/com/alibaba/testable/demo/DemoServiceTest.kt index 71b1a25..79956fa 100644 --- a/demo/kotlin-demo/src/test/kotlin/com/alibaba/testable/demo/DemoServiceTest.kt +++ b/demo/kotlin-demo/src/test/kotlin/com/alibaba/testable/demo/DemoServiceTest.kt @@ -1,8 +1,8 @@ package com.alibaba.testable.demo import com.alibaba.testable.core.accessor.PrivateAccessor -import com.alibaba.testable.core.annotation.EnableTestable -import com.alibaba.testable.core.annotation.TestableInject +import com.alibaba.testable.core.annotation.EnablePrivateAccess +import com.alibaba.testable.core.annotation.TestableMock import com.alibaba.testable.core.tool.TestableTool.SOURCE_METHOD import com.alibaba.testable.core.tool.TestableTool.TEST_CASE import org.junit.jupiter.api.Assertions.assertEquals @@ -10,25 +10,25 @@ import org.junit.jupiter.api.Test import java.util.concurrent.Executors -@EnableTestable +@EnablePrivateAccess internal class DemoServiceTest { - @TestableInject + @TestableMock private fun createBlackBox(text: String) = BlackBox("mock_$text") - @TestableInject + @TestableMock private fun innerFunc(text: String) = "mock_$text" - @TestableInject(targetClass = BlackBox::class) + @TestableMock(targetClass = BlackBox::class) private fun trim(self: BlackBox) = "trim_string" - @TestableInject(targetClass = BlackBox::class, targetMethod = "substring") + @TestableMock(targetClass = BlackBox::class, targetMethod = "substring") private fun sub(self: BlackBox, i: Int, j: Int) = "sub_string" - @TestableInject(targetClass = BlackBox::class) + @TestableMock(targetClass = BlackBox::class) private fun startsWith(self: BlackBox, s: String) = false - @TestableInject + @TestableMock private fun callFromDifferentMethod(): String { return if (TEST_CASE == "should_able_to_get_test_case_name") { "mock_special" diff --git a/docs/ReleaseNote.md b/docs/ReleaseNote.md index 9346f57..71c5307 100644 --- a/docs/ReleaseNote.md +++ b/docs/ReleaseNote.md @@ -3,6 +3,8 @@ ## v0.2.0 - use `TestableTool` class to expose test context - add `testable-maven-plugin` module +- remove dependence on EnableTestable annotation in `testable-agent` +- rename annotations to reflect the actual use ## v0.1.0 - move generated agent jar to class folder diff --git a/docs/Usage.md b/docs/Usage.md index 076c0d5..e89585b 100644 --- a/docs/Usage.md +++ b/docs/Usage.md @@ -40,7 +40,7 @@ ### 访问私有成员字段和方法 -在测试类上添加`@EnableTestable`注解,然后即可直接在单元测试里像访问公有成员一样调用被测类的私有方法、读写私有成员变量了,虽然IDE可能会提升语法有误,但编译器将会正常运行测试。 +在测试类上添加`@EnablePrivateAccess`注解,然后即可直接在单元测试里像访问公有成员一样调用被测类的私有方法、读写私有成员变量了,虽然IDE可能会提升语法有误,但编译器将会正常运行测试。 若不希望看到IDE的语法错误提醒,或是在基于JVM的非Java语言项目里(譬如Kotlin语言),也可以借助`PrivateAccessor`工具类来实现私有成员的访问。 @@ -50,17 +50,17 @@ **【1】覆写任意类的方法调用** -定义一个普通方法,使它与待覆写方法名称和返回值类型完全一致,仅比待覆写方法在首位多一个该方法所属对象类型的参数,然后为这个方法加上`@TestableInject`注解,并设置`targetClass`属性值为被Mock方法的所属类型。 +定义一个普通方法,使它与待覆写方法名称和返回值类型完全一致,仅比待覆写方法在首位多一个该方法所属对象类型的参数,然后为这个方法加上`@TestableMock`注解,并设置`targetClass`属性值为被Mock方法的所属类型。 此时被测类中所有对该类指定方法的调用,将在单元测试运行时,自动被替换为对上述自定义Mock方法的调用。 -`@TestableInject`注解还有一个很少需要用到的`targetMethod`属性,用于指定Mock的目标方法名称。使用此参数后被注释修饰的方法名称就可以随意命名了,通常仅在遇到极其罕见的Mock方法签名重名情况时才需要使用。 +`@TestableMock`注解还有一个很少需要用到的`targetMethod`属性,用于指定Mock的目标方法名称。使用此参数后被注释修饰的方法名称就可以随意命名了,通常仅在遇到极其罕见的Mock方法签名重名情况时才需要使用。 示例项目文件`DemoServiceTest.java`中的`should_able_to_test_common_method()`用例详细展示了这几种用法。 **【2】覆写任意类的new操作** -同样还是定义一个普通方法,然后加上`@TestableInject`注解。方法名称随意,只需让方法的返回值为要覆写new操作的目标类型,且参数与指定类构造方法完全一致。 +同样还是定义一个普通方法,然后加上`@TestableMock`注解。方法名称随意,只需让方法的返回值为要覆写new操作的目标类型,且参数与指定类构造方法完全一致。 此时被测类中所有用`new`创建指定类的操作将被替换为对该自定义方法的调用。 @@ -70,7 +70,7 @@ 有时候,被测类自身的某个成员方法访问了外部系统,在进行单元测试的时候就需要将这个备查样自己的成员方法Mock掉。 -在测试类中声明一个名称、参数和返回值类型都与要覆写的目标方法完全一致的普通方法,同样加上`@TestableInject`注解,不配置`targetClass`属性,即可实现对被测类私有成员方法的覆写。 +在测试类中声明一个名称、参数和返回值类型都与要覆写的目标方法完全一致的普通方法,同样加上`@TestableMock`注解,不配置`targetClass`属性,即可实现对被测类私有成员方法的覆写。 详见示例项目文件`DemoServiceTest.java`中的`should_able_to_test_member_method()`用例。 diff --git a/testable-agent/src/main/java/com/alibaba/testable/agent/constant/ConstPool.java b/testable-agent/src/main/java/com/alibaba/testable/agent/constant/ConstPool.java index cb9bdda..b72b227 100644 --- a/testable-agent/src/main/java/com/alibaba/testable/agent/constant/ConstPool.java +++ b/testable-agent/src/main/java/com/alibaba/testable/agent/constant/ConstPool.java @@ -12,5 +12,5 @@ public class ConstPool { public static final String TEST_POSTFIX = "Test"; public static final String TESTABLE_INJECT_REF = "_testableInternalRef"; - public static final String TESTABLE_INJECT = "com.alibaba.testable.core.annotation.TestableInject"; + public static final String TESTABLE_MOCK = "com.alibaba.testable.core.annotation.TestableMock"; } diff --git a/testable-agent/src/main/java/com/alibaba/testable/agent/handler/TestClassHandler.java b/testable-agent/src/main/java/com/alibaba/testable/agent/handler/TestClassHandler.java index fea1799..b681a4a 100644 --- a/testable-agent/src/main/java/com/alibaba/testable/agent/handler/TestClassHandler.java +++ b/testable-agent/src/main/java/com/alibaba/testable/agent/handler/TestClassHandler.java @@ -52,7 +52,7 @@ public class TestClassHandler extends BaseClassHandler { for (AnnotationNode n : mn.visibleAnnotations) { visibleAnnotationNames.add(n.desc); } - if (visibleAnnotationNames.contains(ClassUtil.toByteCodeClassName(ConstPool.TESTABLE_INJECT))) { + if (visibleAnnotationNames.contains(ClassUtil.toByteCodeClassName(ConstPool.TESTABLE_MOCK))) { mn.access &= ~ACC_PRIVATE; mn.access &= ~ACC_PROTECTED; mn.access |= ACC_PUBLIC; 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 c7bd6ec..1e5b2c5 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 @@ -44,7 +44,7 @@ public class TestableClassTransformer implements ClassFileTransformer { if (shouldTransformAsSourceClass(className)) { // it's a source class with testable enabled loadedClassNames.add(new ComparableWeakRef(className)); - List injectMethods = getTestableInjectMethods(ClassUtil.getTestClassName(className)); + List injectMethods = getTestableMockMethods(ClassUtil.getTestClassName(className)); return new SourceClassHandler(injectMethods).getBytes(classFileBuffer); } else if (shouldTransformAsTestClass(className)) { // it's a test class with testable enabled @@ -58,19 +58,19 @@ public class TestableClassTransformer implements ClassFileTransformer { } private boolean shouldTransformAsSourceClass(String className) { - return ClassUtil.anyMethodHasAnnotation(ClassUtil.getTestClassName(className), ConstPool.TESTABLE_INJECT); + return ClassUtil.anyMethodHasAnnotation(ClassUtil.getTestClassName(className), ConstPool.TESTABLE_MOCK); } private boolean shouldTransformAsTestClass(String className) { return className.endsWith(ConstPool.TEST_POSTFIX) && - ClassUtil.anyMethodHasAnnotation(className, ConstPool.TESTABLE_INJECT); + ClassUtil.anyMethodHasAnnotation(className, ConstPool.TESTABLE_MOCK); } private boolean isSystemClass(ClassLoader loader, String className) { return !(loader instanceof URLClassLoader) || null == className || className.startsWith("jdk/"); } - private List getTestableInjectMethods(String className) { + private List getTestableMockMethods(String className) { try { List methodInfos = new ArrayList(); ClassNode cn = new ClassNode(); @@ -89,7 +89,7 @@ public class TestableClassTransformer implements ClassFileTransformer { return; } for (AnnotationNode an : mn.visibleAnnotations) { - if (toDotSeparateFullClassName(an.desc).equals(ConstPool.TESTABLE_INJECT)) { + if (toDotSeparateFullClassName(an.desc).equals(ConstPool.TESTABLE_MOCK)) { String sourceClassName = ClassUtil.getSourceClassName(cn.name); String targetClass = getAnnotationParameter(an, TARGET_CLASS, sourceClassName); String targetMethod = getAnnotationParameter(an, TARGET_METHOD, mn.name); diff --git a/testable-core/src/main/java/com/alibaba/testable/core/annotation/EnableTestable.java b/testable-core/src/main/java/com/alibaba/testable/core/annotation/EnablePrivateAccess.java similarity index 86% rename from testable-core/src/main/java/com/alibaba/testable/core/annotation/EnableTestable.java rename to testable-core/src/main/java/com/alibaba/testable/core/annotation/EnablePrivateAccess.java index 52e3ea1..bca263a 100644 --- a/testable-core/src/main/java/com/alibaba/testable/core/annotation/EnableTestable.java +++ b/testable-core/src/main/java/com/alibaba/testable/core/annotation/EnablePrivateAccess.java @@ -10,5 +10,5 @@ import java.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Documented -public @interface EnableTestable { +public @interface EnablePrivateAccess { } diff --git a/testable-core/src/main/java/com/alibaba/testable/core/annotation/TestableInject.java b/testable-core/src/main/java/com/alibaba/testable/core/annotation/TestableMock.java similarity index 93% rename from testable-core/src/main/java/com/alibaba/testable/core/annotation/TestableInject.java rename to testable-core/src/main/java/com/alibaba/testable/core/annotation/TestableMock.java index 0316dd7..afb300c 100644 --- a/testable-core/src/main/java/com/alibaba/testable/core/annotation/TestableInject.java +++ b/testable-core/src/main/java/com/alibaba/testable/core/annotation/TestableMock.java @@ -10,7 +10,7 @@ import java.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @Documented -public @interface TestableInject { +public @interface TestableMock { /** * mock method of specified class instead of the class under test diff --git a/testable-core/src/main/java/com/alibaba/testable/core/processor/EnableTestableProcessor.java b/testable-core/src/main/java/com/alibaba/testable/core/processor/EnablePrivateAccessProcessor.java similarity index 89% rename from testable-core/src/main/java/com/alibaba/testable/core/processor/EnableTestableProcessor.java rename to testable-core/src/main/java/com/alibaba/testable/core/processor/EnablePrivateAccessProcessor.java index 47ae9b6..17582d2 100644 --- a/testable-core/src/main/java/com/alibaba/testable/core/processor/EnableTestableProcessor.java +++ b/testable-core/src/main/java/com/alibaba/testable/core/processor/EnablePrivateAccessProcessor.java @@ -1,9 +1,9 @@ package com.alibaba.testable.core.processor; -import com.alibaba.testable.core.annotation.EnableTestable; +import com.alibaba.testable.core.annotation.EnablePrivateAccess; import com.alibaba.testable.core.constant.ConstPool; import com.alibaba.testable.core.model.TestableContext; -import com.alibaba.testable.core.translator.EnableTestableTranslator; +import com.alibaba.testable.core.translator.EnablePrivateAccessTranslator; import com.alibaba.testable.core.util.TestableLogger; import com.sun.tools.javac.api.JavacTrees; import com.sun.tools.javac.code.Symbol; @@ -26,8 +26,8 @@ import java.util.Set; /** * @author flin */ -@SupportedAnnotationTypes("com.alibaba.testable.core.annotation.EnableTestable") -public class EnableTestableProcessor extends AbstractProcessor { +@SupportedAnnotationTypes("com.alibaba.testable.core.annotation.EnablePrivateAccess") +public class EnablePrivateAccessProcessor extends AbstractProcessor { private TestableContext cx; @@ -59,7 +59,7 @@ public class EnableTestableProcessor extends AbstractProcessor { if (cx.names == null) { return true; } - Set elements = roundEnv.getElementsAnnotatedWith(EnableTestable.class); + Set elements = roundEnv.getElementsAnnotatedWith(EnablePrivateAccess.class); for (Element element : elements) { if (element.getKind().isClass() && isTestClass(element.getSimpleName())) { processClassElement((Symbol.ClassSymbol)element); @@ -81,7 +81,7 @@ public class EnableTestableProcessor extends AbstractProcessor { private void processClassElement(Symbol.ClassSymbol clazz) { JCTree tree = cx.trees.getTree(clazz); String pkgName = ((Symbol.PackageSymbol)clazz.owner).fullname.toString(); - tree.accept(new EnableTestableTranslator(pkgName, clazz.getSimpleName().toString(), cx)); + tree.accept(new EnablePrivateAccessTranslator(pkgName, clazz.getSimpleName().toString(), cx)); } } diff --git a/testable-core/src/main/java/com/alibaba/testable/core/translator/EnableTestableTranslator.java b/testable-core/src/main/java/com/alibaba/testable/core/translator/EnablePrivateAccessTranslator.java similarity index 96% rename from testable-core/src/main/java/com/alibaba/testable/core/translator/EnableTestableTranslator.java rename to testable-core/src/main/java/com/alibaba/testable/core/translator/EnablePrivateAccessTranslator.java index 7473891..cedc798 100644 --- a/testable-core/src/main/java/com/alibaba/testable/core/translator/EnableTestableTranslator.java +++ b/testable-core/src/main/java/com/alibaba/testable/core/translator/EnablePrivateAccessTranslator.java @@ -16,7 +16,7 @@ import java.lang.reflect.Modifier; * * @author flin */ -public class EnableTestableTranslator extends BaseTranslator { +public class EnablePrivateAccessTranslator extends BaseTranslator { private final String sourceClassName; private final ListBuffer sourceClassIns = new ListBuffer(); @@ -24,7 +24,7 @@ public class EnableTestableTranslator extends BaseTranslator { private final ListBuffer privateMethods = new ListBuffer(); private final PrivateAccessStatementGenerator privateAccessStatementGenerator; - public EnableTestableTranslator(String pkgName, String testClassName, TestableContext cx) { + public EnablePrivateAccessTranslator(String pkgName, String testClassName, TestableContext cx) { this.sourceClassName = testClassName.substring(0, testClassName.length() - ConstPool.TEST_POSTFIX.length()); this.privateAccessStatementGenerator = new PrivateAccessStatementGenerator(cx); try { diff --git a/testable-core/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/testable-core/src/main/resources/META-INF/services/javax.annotation.processing.Processor index 35df998..c5c34d5 100644 --- a/testable-core/src/main/resources/META-INF/services/javax.annotation.processing.Processor +++ b/testable-core/src/main/resources/META-INF/services/javax.annotation.processing.Processor @@ -1 +1 @@ -com.alibaba.testable.core.processor.EnableTestableProcessor +com.alibaba.testable.core.processor.EnablePrivateAccessProcessor