bump to v0.4.8

This commit is contained in:
金戟 2021-01-08 08:14:12 +08:00
parent 444967f676
commit c1744d2254
15 changed files with 71 additions and 48 deletions

View File

@ -13,8 +13,8 @@ repositories {
dependencies {
testImplementation('org.junit.jupiter:junit-jupiter:5.6.2')
testImplementation('com.alibaba.testable:testable-all:0.4.7')
testAnnotationProcessor('com.alibaba.testable:testable-processor:0.4.7')
testImplementation('com.alibaba.testable:testable-all:0.4.8')
testAnnotationProcessor('com.alibaba.testable:testable-processor:0.4.8')
}
tasks.withType(JavaCompile) {

View File

@ -12,7 +12,7 @@
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<junit.version>5.6.2</junit.version>
<testable.version>0.4.7</testable.version>
<testable.version>0.4.8</testable.version>
</properties>
<dependencies>

View File

@ -16,8 +16,8 @@ dependencies {
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
testImplementation("org.junit.jupiter:junit-jupiter:5.6.2")
testImplementation("com.alibaba.testable:testable-all:0.4.7")
testAnnotationProcessor("com.alibaba.testable:testable-processor:0.4.7")
testImplementation("com.alibaba.testable:testable-all:0.4.8")
testAnnotationProcessor("com.alibaba.testable:testable-processor:0.4.8")
}
tasks.withType<KotlinCompile> {

View File

@ -14,7 +14,7 @@
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<junit.version>5.6.2</junit.version>
<testable.version>0.4.7</testable.version>
<testable.version>0.4.8</testable.version>
</properties>
<dependencies>

View File

@ -1,5 +1,10 @@
# Release Note
## 0.4.8
- Fix an issue of private method invocation failed in assignment statements
- Support using mock for testing with `SpringRunner`
- Support `targetClass` parameter in `@MockMethod` annotation
## 0.4.7
- Fix incorrect stack size caused by `MOCK_CONTEXT` variable initialization
- Fix incorrect gradle build path of under Windows operating system

View File

@ -15,7 +15,7 @@ It is recommended to add a `property` field that identifies the TestableMock ver
```xml
<properties>
<testable.version>0.4.7</testable.version>
<testable.version>0.4.8</testable.version>
</properties>
```
@ -62,8 +62,8 @@ Add dependence of `TestableMock` in `build.gradle` file:
```groovy
dependencies {
testImplementation('com.alibaba.testable:testable-all:0.4.7')
testAnnotationProcessor('com.alibaba.testable:testable-processor:0.4.7')
testImplementation('com.alibaba.testable:testable-all:0.4.8')
testAnnotationProcessor('com.alibaba.testable:testable-processor:0.4.8')
}
```

View File

@ -1,12 +1,17 @@
# Release Note
## 0.4.8
- 修复赋值语句中的私有方法调用无法访问的BUG (issue-33)
- 支持在包含`SpringRunner`的测试中使用Mock (issue-30)
- `@MockMethod`注解支持`targetClass`参数 (issue-24)
## 0.4.7
- 修复由于`MOCK_CONTEXT`引入的堆栈大小错误
- 修复Windows下的`Gradle`构建路径错误
- 修复Windows下的`Gradle`构建路径错误 (issue-25)
## 0.4.6
- 修复一处`IINC`字节码处理异常
- 支持使用`TestableTool.MOCK_CONTEXT`变量为Mock方法注入额外上下文参数
- 支持使用`TestableTool.MOCK_CONTEXT`变量为Mock方法注入额外上下文参数 (issue-17)
- 不再推荐使用`TestableTool.TEST_CASE`变量来区分测试用例
## 0.4.5

View File

@ -15,7 +15,7 @@
```xml
<properties>
<testable.version>0.4.7</testable.version>
<testable.version>0.4.8</testable.version>
</properties>
```
@ -62,8 +62,8 @@
```groovy
dependencies {
testImplementation('com.alibaba.testable:testable-all:0.4.7')
testAnnotationProcessor('com.alibaba.testable:testable-processor:0.4.7')
testImplementation('com.alibaba.testable:testable-all:0.4.8')
testAnnotationProcessor('com.alibaba.testable:testable-processor:0.4.8')
}
```

View File

@ -4,89 +4,104 @@
相比以往Mock工具以类为粒度的Mock方式`TestableMock`允许用户直接定义需要Mock的单个方法并遵循约定优于配置的原则按照规则自动在测试运行时替换被测方法中的指定方法调用。
> 归纳起来就两条:
> - Mock非构造方法拷贝原方法定义到测试类增加一个与调用者类型相同的参数,加`@MockMethod`注解
> - Mock非构造方法拷贝原方法定义到测试类加`@MockMethod`注解
> - Mock构造方法拷贝原方法定义到测试类返回值换成构造的类型方法名随意加`@MockContructor`注解
> **Mock约定**
> - 测试类与被测类的包路径应相同,且名称为`被测类名+Test`。通常采用`Maven`或`Gradle`构建的Java项目均符合这种惯例。此约定在未来的`TestableMock`版本中可能会被放宽或去除(请关注[Issue-12](https://github.com/alibaba/testable-mock/issues/12))。
> - 请勿在Mock方法的定义中访问任何非静态成员。当前包含`@MockMethod`或`@MockContructor`注解的方法会在运行期被自动修改为静态(`static`)方法。此约定在未来的版本中将被去除,请留意相关更新。
> - 请勿在Mock方法的定义中访问任何非静态成员。此约定在计划在`0.5`版本中去除,请留意相关更新。
> **特别说明**
> - 当前Mock方法即包含`@MockMethod`或`@MockContructor`注解的方法)会在运行期被自动修改为`static`方法当Mock方法内容较复杂包含Lambda语句、构造块、匿名类等编译器会在构建期生成额外的非静态临时方法导致"Bad type in operand stack"错误。如果有遇到此类错误请将Mock方法显式加上`static`修饰即可解决。这个问题会在`0.5`版本中彻底解决。
具体的Mock方法定义约定如下
#### 1. 覆写任意类的方法调用
在测试类里定义一个有`@MockMethod`注解的普通方法,使它与需覆写的方法名称、参数、返回值类型完全一致,然后在其参数列表首位再增加一个类型为该方法原本所属对象类型的参数
在测试类里定义一个有`@MockMethod`注解的普通方法,使它与需覆写的方法名称、参数、返回值类型完全一致,并在注解的`targetClass`参数指定该方法原本所属对象类型
此时被测类中所有对该需覆写方法的调用将在单元测试运行时将自动被替换为对上述自定义Mock方法的调用。
**注意**:当遇到待覆写方法有重名时,可以将需覆写的方法名写到`@MockMethod`注解的`targetMethod`参数里这样Mock方法自身就可以随意命名了。
例如,被测类中有一处`"anything".substring(1, 2)`调用,我们希望在运行测试的时候将它换成一个固定字符串,则只需在测试类定义如下方法:
```java
// 原方法签名为`String substring(int, int)`
// 调用此方法的对象`"anything"`类型为`String`
// 则Mock方法签名在其参数列表首位增加一个类型为`String`的参数(名字随意)
// 此参数可用于获得当时的实际调用者的值和上下文
@MockMethod
private String substring(String self, int i, int j) {
@MockMethod(targetClass = String.class)
private String substring(int i, int j) {
return "sub_string";
}
```
当遇到待覆写方法有重名时,可以将需覆写的方法名写到`@MockMethod`注解的`targetMethod`参数里这样Mock方法自身就可以随意命名了。
下面这个例子展示了`targetMethod`参数的用法,其效果与上述示例相同:
```java
// 使用`targetMethod`指定需Mock的方法名
// 此方法本身现在可以随意命名,但方法参数依然需要遵循相同的匹配规则
@MockMethod(targetMethod = "substring")
private String use_any_mock_method_name(String self, int i, int j) {
@MockMethod(targetClass = String.class, targetMethod = "substring")
private String use_any_mock_method_name(int i, int j) {
return "sub_string";
}
```
有时在Mock方法里会需要访问发起调用的原始对象中的成员变量或是调用原始对象的其他方法。此时可以将`@MockMethod`注解中的`targetClass`参数去除,然后在方法参数列表首位增加一个类型为该方法原本所属对象类型的参数。
`TestableMock`约定,当`@MockMethod`注解的`targetClass`参数值为空时Mock方法的首位参数即为目标方法所属类型参数名称随意。通常为了便于代码阅读建议将此参数统一命名为`self`或`src`。举例如下:
```java
// Mock方法在参数列表首位增加一个类型为`String`的参数(名字随意)
// 此参数可用于获得当时的实际调用者的值和上下文
@MockMethod
private String substring(String self, int i, int j) {
// 可以直接调用原方法此时Mock方法仅用于记录调用常见于对void方法的测试
return self.substring(i, j);
}
```
完整代码示例见`java-demo`和`kotlin-demo`示例项目中的`should_able_to_mock_common_method()`测试用例。(由于Kotlin对String类型进行了魔改故Kotlin示例中将被测方法在`BlackBox`类里加了一层封装)
#### 2. 覆写被测类自身的成员方法
有时候在对某些方法进行测试时希望将被测类自身的另外一些成员方法Mock掉。
有时候在对某些方法进行测试时希望将被测类自身的另外一些成员方法Mock掉(比如这个方法里有许多外部依赖或耗时操作)
操作方法与前一种情况相同Mock方法的第一个参数类型需与被测类相同即可实现对被测类自身不论是公有或私有成员方法的覆写。
做法与前一种情况完全相同,只需将`targetClass`参数赋值为被测类,即可实现对被测类自身(不论是公有或私有)成员方法的覆写。
例如,被测类中有一个签名为`String innerFunc(String)`的私有方法,我们希望在测试的时候将它替换掉,则只需在测试类定义如下方法:
```java
// 被测类型是`DemoMock`
// 因此在定义Mock方法时在目标方法参数首位加一个类型为`DemoMock`的参数(名字随意)
@MockMethod
private String innerFunc(DemoMock self, String text) {
@MockMethod(targetClass = DemoMock.class)
private String innerFunc(String text) {
return "mock_" + text;
}
```
同样的,上述示例中的方法如需访问发起调用的原始被测对象,也可不使用`targetClass`参数而是在定义Mock方法时在方法参数列表首位加一个类型为`DemoMock`的参数(名字随意)。
完整代码示例见`java-demo`和`kotlin-demo`示例项目中的`should_able_to_mock_member_method()`测试用例。
#### 3. 覆写任意类的静态方法
对于静态方法的Mock与普通方法相同。但需要注意的是静态方法的Mock方法被调用时传入的第一个参数实际值始终是`null`。
对于静态方法的Mock与普通方法相同。
例如,在被测类中调用了`BlackBox`类型中的静态方法`secretBox()`方法签名为`BlackBox secretBox()`则Mock方法如下
例如,在被测类中调用了`BlackBox`类型中的静态方法`secretBox()`方法签名为`BlackBox secretBox()`则Mock方法如下
```java
// 目标静态方法定义在`BlackBox`类型中
// 在定义Mock方法时在目标方法参数首位加一个类型为`BlackBox`的参数(名字随意)
// 此参数仅用于标识目标类型,实际传入值将始终为`null`
@MockMethod
private BlackBox secretBox(BlackBox ignore) {
@MockMethod(targetClass = BlackBox.class)
private BlackBox secretBox() {
return new BlackBox("not_secret_box");
}
```
对于静态方法的Mock通常不使用方法参数列表的首位加参数来表示目标类型。但这种方法也依然适用只是实际传入的第一个参数值将始终是`null`。
完整代码示例见`java-demo`和`kotlin-demo`示例项目中的`should_able_to_mock_static_method()`测试用例。
#### 4. 覆写任意类的new操作
在测试类里定义一个有`@MockContructor`注解的普通方法,使该方法返回值类型为要被创建的对象类型且方法参数与要Mock的构造函数参数完全一致,方法名称随意
在测试类里定义一个返回值类型为要被创建的对象类型且方法参数与要Mock的构造函数参数完全一致的方法,名称随意,然后加上`@MockContructor`注解
此时被测类中所有用`new`创建指定类的操作并使用了与Mock方法参数一致的构造函数将被替换为对该自定义方法的调用。
@ -94,15 +109,13 @@ private BlackBox secretBox(BlackBox ignore) {
```java
// 要覆写的构造函数签名为`BlackBox(String)`
// 无需在Mock方法参数列表增加额外参数Mock方法的名称随意起
// Mock方法返回`BlackBox`类型对象,方法的名称随意起
@MockContructor
private BlackBox createBlackBox(String text) {
return new BlackBox("mock_" + text);
}
```
> 也可以依然使用`@MockMethod`注解,并配置`targetMethod`参数值为`"<init>"`,其余同上。效果与使用`@MockContructor`注解相同
完整代码示例见`java-demo`和`kotlin-demo`示例项目中的`should_able_to_mock_new_object()`测试用例。
#### 5. 识别当前测试用例和调用来源

View File

@ -6,7 +6,7 @@
<parent>
<groupId>com.alibaba.testable</groupId>
<artifactId>testable-parent</artifactId>
<version>0.4.7</version>
<version>0.4.8</version>
<relativePath>../testable-parent</relativePath>
</parent>
<artifactId>testable-agent</artifactId>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>com.alibaba.testable</groupId>
<artifactId>testable-parent</artifactId>
<version>0.4.7</version>
<version>0.4.8</version>
<relativePath>../testable-parent</relativePath>
</parent>
<artifactId>testable-all</artifactId>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>com.alibaba.testable</groupId>
<artifactId>testable-parent</artifactId>
<version>0.4.7</version>
<version>0.4.8</version>
<relativePath>../testable-parent</relativePath>
</parent>
<artifactId>testable-core</artifactId>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>com.alibaba.testable</groupId>
<artifactId>testable-parent</artifactId>
<version>0.4.7</version>
<version>0.4.8</version>
<relativePath>../testable-parent</relativePath>
</parent>
<artifactId>testable-maven-plugin</artifactId>

View File

@ -5,7 +5,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.alibaba.testable</groupId>
<artifactId>testable-parent</artifactId>
<version>0.4.7</version>
<version>0.4.8</version>
<packaging>pom</packaging>
<name>testable-parent</name>
<description>Unit test enhancement toolkit</description>
@ -42,7 +42,7 @@
<plugin.gpg.version>1.6</plugin.gpg.version>
<plugin.staging.version>1.6.8</plugin.staging.version>
<plugin.maven.version>3.6.0</plugin.maven.version>
<testable.version>0.4.7</testable.version>
<testable.version>0.4.8</testable.version>
</properties>
<profiles>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>com.alibaba.testable</groupId>
<artifactId>testable-parent</artifactId>
<version>0.4.7</version>
<version>0.4.8</version>
<relativePath>../testable-parent</relativePath>
</parent>
<artifactId>testable-processor</artifactId>