split core package into core and processor

This commit is contained in:
金戟 2020-10-27 06:54:36 +08:00
parent 419a10669d
commit 989a52a048
30 changed files with 171 additions and 57 deletions

View File

@ -8,7 +8,8 @@
## 目录结构
```bash
|-- testable-core ➜ 核心组件,提供测试辅助功能、注解和工具类
|-- testable-core ➜ 核心组件,提供注解和工具类
|-- testable-processor ➜ 编译期代码预处理组件,提供测试辅助功能
|-- testable-agent ➜ JavaAgent组件提供Mock测试相关功能
|-- testable-maven-plugin ➜ Maven插件组件用于简化JavaAgent注入
|-- demo

View File

@ -27,7 +27,7 @@
<dependency>
<groupId>com.alibaba.testable</groupId>
<artifactId>testable-core</artifactId>
<artifactId>testable-processor</artifactId>
<version>${testable.version}</version>
<scope>provided</scope>
</dependency>

View File

@ -12,4 +12,8 @@ public class BlackBox {
return data;
}
public static BlackBox secretBox() {
return new BlackBox("secret");
}
}

View File

@ -47,6 +47,13 @@ public class DemoService {
return "anything".trim() + "__" + "anything".substring(1, 2) + "__" + "abc".startsWith("ab");
}
/**
* Target 6 - method with static method invoke
*/
public BlackBox getBox() {
return BlackBox.secretBox();
}
public String callerOne() {
return callFromDifferentMethod();
}

View File

@ -1,7 +1,7 @@
package com.alibaba.testable.demo;
import com.alibaba.testable.core.accessor.PrivateAccessor;
import com.alibaba.testable.core.annotation.EnablePrivateAccess;
import com.alibaba.testable.processor.annotation.EnablePrivateAccess;
import com.alibaba.testable.core.annotation.TestableMock;
import org.junit.jupiter.api.Test;
@ -38,6 +38,11 @@ class DemoServiceTest {
return false;
}
@TestableMock
private BlackBox secretBox() {
return new BlackBox("not_secret_box");
}
@TestableMock
private String callFromDifferentMethod(DemoService self) {
if (TEST_CASE.equals("should_able_to_get_test_case_name")) {
@ -52,13 +57,13 @@ class DemoServiceTest {
private DemoService demoService = new DemoService();
@Test
void should_able_to_test_private_method() throws Exception {
void should_able_to_mock_private_method() throws Exception {
assertEquals("hello - 1", demoService.privateFunc("hello", 1));
assertEquals("hello - 1", PrivateAccessor.invoke(demoService, "privateFunc", "hello", 1));
}
@Test
void should_able_to_test_private_field() throws Exception {
void should_able_to_mock_private_field() throws Exception {
demoService.count = 2;
assertEquals("4", demoService.privateFieldAccessFunc());
PrivateAccessor.set(demoService, "count", 3);
@ -67,19 +72,19 @@ class DemoServiceTest {
}
@Test
void should_able_to_test_new_object() throws Exception {
void should_able_to_mock_new_object() throws Exception {
assertEquals("mock_something", demoService.newFunc());
verify("createBlackBox").times(1);
}
@Test
void should_able_to_test_member_method() throws Exception {
void should_able_to_mock_member_method() throws Exception {
assertEquals("{ \"res\": \"mock_hello\"}", demoService.outerFunc("hello"));
verify("innerFunc").times(1);
}
@Test
void should_able_to_test_common_method() throws Exception {
void should_able_to_mock_common_method() throws Exception {
assertEquals("trim_string__sub_string__false", demoService.commonFunc());
verify("trim").times(1);
verify("sub").times(1);

View File

@ -40,7 +40,7 @@
<dependency>
<groupId>com.alibaba.testable</groupId>
<artifactId>testable-core</artifactId>
<artifactId>testable-processor</artifactId>
<version>${testable.version}</version>
<scope>provided</scope>
</dependency>

View File

@ -19,4 +19,16 @@ class BlackBox(private val data: String) {
return data.startsWith(prefix)
}
companion object {
fun secretBox(): BlackBox {
return BlackBox("secret")
}
}
}
object ColorBox {
fun createBox(color: String): BlackBox {
return BlackBox("${color}_Box")
}
}

View File

@ -1,7 +1,7 @@
package com.alibaba.testable.demo
import com.alibaba.testable.core.accessor.PrivateAccessor
import com.alibaba.testable.core.annotation.EnablePrivateAccess
import com.alibaba.testable.processor.annotation.EnablePrivateAccess
import com.alibaba.testable.core.annotation.TestableMock
import com.alibaba.testable.core.tool.TestableTool.*
import org.junit.jupiter.api.Assertions.assertEquals
@ -42,31 +42,31 @@ internal class DemoServiceTest {
private val demoService = DemoService()
@Test
fun should_able_to_test_private_method() {
fun should_able_to_mock_private_method() {
assertEquals("hello - 1", PrivateAccessor.invoke(demoService, "privateFunc", "hello", 1))
}
@Test
fun should_able_to_test_private_field() {
fun should_able_to_mock_private_field() {
PrivateAccessor.set(demoService, "count", 3)
assertEquals("5", demoService.privateFieldAccessFunc())
assertEquals(5, PrivateAccessor.get(demoService, "count"))
}
@Test
fun should_able_to_test_new_object() {
fun should_able_to_mock_new_object() {
assertEquals("mock_something", demoService.newFunc())
verify("createBlackBox").times(1)
}
@Test
fun should_able_to_test_member_method() {
fun should_able_to_mock_member_method() {
assertEquals("{ \"res\": \"mock_hello\"}", demoService.outerFunc("hello"))
verify("innerFunc").times(1)
}
@Test
fun should_able_to_test_common_method() {
fun should_able_to_mock_common_method() {
assertEquals("trim_string__sub_string__false", demoService.commonFunc())
verify("trim").times(1)
verify("sub").times(1)

View File

@ -3,12 +3,12 @@
## 引入Testable
首先在项目`pom.xml`文件中添加`testable-core`依赖:
首先在项目`pom.xml`文件中添加`testable-processor`依赖:
```xml
<dependency>
<groupId>com.alibaba.testable</groupId>
<artifactId>testable-core</artifactId>
<artifactId>testable-processor</artifactId>
<version>${testable.version}</version>
<scope>provided</scope>
</dependency>
@ -51,7 +51,7 @@
若不希望看到IDE的语法错误提醒或是在基于JVM的非Java语言项目里譬如Kotlin语言也可以借助`PrivateAccessor`工具类来实现私有成员的访问。
效果见示例项目文件`DemoServiceTest.java`中的`should_able_to_test_private_method()`和`should_able_to_test_private_field()`测试用例。
效果见示例项目文件`DemoServiceTest.java`中的`should_able_to_mock_private_method()`和`should_able_to_mock_private_field()`测试用例。
### Mock被测类的任意方法调用
@ -63,7 +63,7 @@
**注意**:当遇到有两个需覆写的方法重名时,可将需覆写的方法名写到`@TestableMock`注解的`targetMethod`参数里此时Mock方法自身就可以随意命名了。
示例项目文件`DemoServiceTest.java`中的`should_able_to_test_common_method()`用例详细展示了这种用法。
示例项目文件`DemoServiceTest.java`中的`should_able_to_mock_common_method()`用例详细展示了这种用法。
**【2】覆写被测类自身的成员方法**
@ -71,7 +71,7 @@
操作方法与前一种情况相同Mock方法的第一个参数类型需与被测类相同即可实现对被测类自身不论是公有或私有成员方法的覆写。
详见示例项目文件`DemoServiceTest.java`中的`should_able_to_test_member_method()`用例。
详见示例项目文件`DemoServiceTest.java`中的`should_able_to_mock_member_method()`用例。
**【3】覆写任意类的new操作**
@ -79,7 +79,7 @@
此时被测类中所有用`new`创建指定类的操作并使用了与Mock方法参数一致的构造函数将被替换为对该自定义方法的调用。
详见示例项目文件`DemoServiceTest.java`中的`should_able_to_test_new_object()`用例。
详见示例项目文件`DemoServiceTest.java`中的`should_able_to_mock_new_object()`用例。
**【4】识别当前测试用例和调用来源**

View File

@ -10,6 +10,7 @@
<modules>
<module>testable-core</module>
<module>testable-processor</module>
<module>testable-agent</module>
<module>testable-maven-plugin</module>
<module>demo</module>

View File

@ -14,6 +14,7 @@
<project.compiler.level>1.6</project.compiler.level>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<asm.lib.version>8.0.1</asm.lib.version>
<junit.version>5.6.2</junit.version>
<testable.version>0.2.1-SNAPSHOT</testable.version>
<plugin.compiler.version>3.8.1</plugin.compiler.version>
<plugin.jar.version>3.2.0</plugin.jar.version>
@ -29,7 +30,7 @@
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.6.2</version>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>

View File

@ -15,20 +15,14 @@
<project.compiler.level>1.6</project.compiler.level>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<plugin.compiler.version>3.8.1</plugin.compiler.version>
<junit.version>5.6.2</junit.version>
</properties>
<dependencies>
<dependency>
<groupId>sun.jdk</groupId>
<artifactId>tools</artifactId>
<version>${java.version}</version>
<scope>system</scope>
<systemPath>${java.home}/../lib/tools.jar</systemPath>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.6.2</version>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
@ -43,7 +37,6 @@
<source>${project.compiler.level}</source>
<target>${project.compiler.level}</target>
<encoding>${project.build.sourceEncoding}</encoding>
<compilerArgument>-proc:none</compilerArgument>
</configuration>
</plugin>
</plugins>

View File

@ -1,5 +1,7 @@
package com.alibaba.testable.core.annotation;
import com.alibaba.testable.core.model.MockType;
import java.lang.annotation.*;
/**
@ -12,6 +14,11 @@ import java.lang.annotation.*;
@Documented
public @interface TestableMock {
/**
* type of mock method
*/
MockType value() default MockType.MEMBER_METHOD;
/**
* mock specified method instead of method with same name
*/

View File

@ -5,7 +5,6 @@ package com.alibaba.testable.core.constant;
*/
public final class ConstPool {
public static final String TESTABLE_PRIVATE_ACCESSOR = "com.alibaba.testable.core.accessor.PrivateAccessor";
public static final String TEST_POSTFIX = "Test";
}

View File

@ -0,0 +1,14 @@
package com.alibaba.testable.core.model;
/**
* Type of mock method
*
* @author flin
*/
public enum MockType {
MEMBER_METHOD,
STATIC_METHOD,
CONSTRUCTOR
}

View File

@ -36,7 +36,7 @@ public class TypeUtil {
/**
* type equals
*/
public static boolean typeEquals(Class<?>[] classesLeft, Class<?>[] classesRight) {
private static boolean typeEquals(Class<?>[] classesLeft, Class<?>[] classesRight) {
if (classesLeft.length != classesRight.length) {
return false;
}

View File

@ -1 +0,0 @@
com.alibaba.testable.core.processor.EnablePrivateAccessProcessor

View File

@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<description>Unit test enhancement toolkit</description>
<groupId>com.alibaba.testable</groupId>
<artifactId>testable-processor</artifactId>
<version>0.2.1-SNAPSHOT</version>
<name>testable-processor</name>
<properties>
<java.version>1.6</java.version>
<project.compiler.level>1.6</project.compiler.level>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<plugin.compiler.version>3.8.1</plugin.compiler.version>
<junit.version>5.6.2</junit.version>
<testable.version>0.2.1-SNAPSHOT</testable.version>
</properties>
<dependencies>
<dependency>
<groupId>com.alibaba.testable</groupId>
<artifactId>testable-core</artifactId>
<version>${testable.version}</version>
</dependency>
<dependency>
<groupId>sun.jdk</groupId>
<artifactId>tools</artifactId>
<version>${java.version}</version>
<scope>system</scope>
<systemPath>${java.home}/../lib/tools.jar</systemPath>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${plugin.compiler.version}</version>
<configuration>
<source>${project.compiler.level}</source>
<target>${project.compiler.level}</target>
<encoding>${project.build.sourceEncoding}</encoding>
<compilerArgument>-proc:none</compilerArgument>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,10 +1,10 @@
package com.alibaba.testable.core.processor;
package com.alibaba.testable.processor;
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.EnablePrivateAccessTranslator;
import com.alibaba.testable.core.util.TestableLogger;
import com.alibaba.testable.processor.annotation.EnablePrivateAccess;
import com.alibaba.testable.processor.constant.ConstPool;
import com.alibaba.testable.processor.model.TestableContext;
import com.alibaba.testable.processor.translator.EnablePrivateAccessTranslator;
import com.alibaba.testable.processor.util.TestableLogger;
import com.sun.tools.javac.api.JavacTrees;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.processing.JavacProcessingEnvironment;
@ -26,7 +26,7 @@ import java.util.Set;
/**
* @author flin
*/
@SupportedAnnotationTypes("com.alibaba.testable.core.annotation.EnablePrivateAccess")
@SupportedAnnotationTypes("com.alibaba.testable.processor.annotation.EnablePrivateAccess")
public class EnablePrivateAccessProcessor extends AbstractProcessor {
private TestableContext cx;

View File

@ -1,4 +1,4 @@
package com.alibaba.testable.core.annotation;
package com.alibaba.testable.processor.annotation;
import java.lang.annotation.*;

View File

@ -0,0 +1,11 @@
package com.alibaba.testable.processor.constant;
/**
* @author flin
*/
public final class ConstPool {
public static final String TESTABLE_PRIVATE_ACCESSOR = "com.alibaba.testable.core.accessor.PrivateAccessor";
public static final String TEST_POSTFIX = "Test";
}

View File

@ -1,6 +1,6 @@
package com.alibaba.testable.core.generator;
package com.alibaba.testable.processor.generator;
import com.alibaba.testable.core.model.TestableContext;
import com.alibaba.testable.processor.model.TestableContext;
import com.sun.tools.javac.tree.JCTree.*;
/**

View File

@ -1,7 +1,7 @@
package com.alibaba.testable.core.generator;
package com.alibaba.testable.processor.generator;
import com.alibaba.testable.core.model.TestableContext;
import com.alibaba.testable.core.constant.ConstPool;
import com.alibaba.testable.processor.model.TestableContext;
import com.alibaba.testable.processor.constant.ConstPool;
import com.sun.tools.javac.tree.JCTree.*;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer;

View File

@ -1,6 +1,6 @@
package com.alibaba.testable.core.model;
package com.alibaba.testable.processor.model;
import com.alibaba.testable.core.util.TestableLogger;
import com.alibaba.testable.processor.util.TestableLogger;
import com.sun.tools.javac.api.JavacTrees;
import com.sun.tools.javac.tree.TreeMaker;
import com.sun.tools.javac.util.Names;

View File

@ -1,4 +1,4 @@
package com.alibaba.testable.core.translator;
package com.alibaba.testable.processor.translator;
import com.sun.tools.javac.tree.JCTree.*;
import com.sun.tools.javac.tree.TreeTranslator;

View File

@ -1,8 +1,8 @@
package com.alibaba.testable.core.translator;
package com.alibaba.testable.processor.translator;
import com.alibaba.testable.core.constant.ConstPool;
import com.alibaba.testable.core.generator.PrivateAccessStatementGenerator;
import com.alibaba.testable.core.model.TestableContext;
import com.alibaba.testable.processor.constant.ConstPool;
import com.alibaba.testable.processor.generator.PrivateAccessStatementGenerator;
import com.alibaba.testable.processor.model.TestableContext;
import com.sun.tools.javac.tree.JCTree.*;
import com.sun.tools.javac.util.ListBuffer;
import com.sun.tools.javac.util.Name;

View File

@ -1,4 +1,4 @@
package com.alibaba.testable.core.util;
package com.alibaba.testable.processor.util;
import java.util.List;

View File

@ -1,4 +1,4 @@
package com.alibaba.testable.core.util;
package com.alibaba.testable.processor.util;
import javax.annotation.processing.Messager;
import javax.tools.Diagnostic;

View File

@ -0,0 +1 @@
com.alibaba.testable.processor.EnablePrivateAccessProcessor

View File

@ -1,4 +1,4 @@
package com.alibaba.testable.core.util;
package com.alibaba.testable.processor.util;
import org.junit.jupiter.api.Test;