diff --git a/demo/java-demo/build.gradle b/demo/java-demo/build.gradle index dd7bcc1..807bbd7 100644 --- a/demo/java-demo/build.gradle +++ b/demo/java-demo/build.gradle @@ -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) { diff --git a/demo/java-demo/pom.xml b/demo/java-demo/pom.xml index 97d861a..fa13036 100644 --- a/demo/java-demo/pom.xml +++ b/demo/java-demo/pom.xml @@ -12,7 +12,7 @@ 1.8 1.8 5.6.2 - 0.4.7 + 0.4.8 diff --git a/demo/kotlin-demo/build.gradle.kts b/demo/kotlin-demo/build.gradle.kts index a383508..adf514c 100644 --- a/demo/kotlin-demo/build.gradle.kts +++ b/demo/kotlin-demo/build.gradle.kts @@ -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 { diff --git a/demo/kotlin-demo/pom.xml b/demo/kotlin-demo/pom.xml index af2e842..b44a400 100644 --- a/demo/kotlin-demo/pom.xml +++ b/demo/kotlin-demo/pom.xml @@ -14,7 +14,7 @@ 1.8 1.8 5.6.2 - 0.4.7 + 0.4.8 diff --git a/docs/en-us/doc/release-note.md b/docs/en-us/doc/release-note.md index cc9b16e..9e62ac5 100644 --- a/docs/en-us/doc/release-note.md +++ b/docs/en-us/doc/release-note.md @@ -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 diff --git a/docs/en-us/doc/setup.md b/docs/en-us/doc/setup.md index 9c23c0f..8b2aedc 100644 --- a/docs/en-us/doc/setup.md +++ b/docs/en-us/doc/setup.md @@ -15,7 +15,7 @@ It is recommended to add a `property` field that identifies the TestableMock ver ```xml - 0.4.7 + 0.4.8 ``` @@ -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') } ``` diff --git a/docs/zh-cn/doc/release-note.md b/docs/zh-cn/doc/release-note.md index f440453..e3b214d 100644 --- a/docs/zh-cn/doc/release-note.md +++ b/docs/zh-cn/doc/release-note.md @@ -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 diff --git a/docs/zh-cn/doc/setup.md b/docs/zh-cn/doc/setup.md index 64afcdd..05ecebd 100644 --- a/docs/zh-cn/doc/setup.md +++ b/docs/zh-cn/doc/setup.md @@ -15,7 +15,7 @@ ```xml - 0.4.7 + 0.4.8 ``` @@ -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') } ``` diff --git a/docs/zh-cn/doc/use-mock.md b/docs/zh-cn/doc/use-mock.md index 3661cf7..c543719 100644 --- a/docs/zh-cn/doc/use-mock.md +++ b/docs/zh-cn/doc/use-mock.md @@ -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`参数值为`""`,其余同上。效果与使用`@MockContructor`注解相同 - 完整代码示例见`java-demo`和`kotlin-demo`示例项目中的`should_able_to_mock_new_object()`测试用例。 #### 5. 识别当前测试用例和调用来源 diff --git a/testable-agent/pom.xml b/testable-agent/pom.xml index fe2b428..31f3e45 100755 --- a/testable-agent/pom.xml +++ b/testable-agent/pom.xml @@ -6,7 +6,7 @@ com.alibaba.testable testable-parent - 0.4.7 + 0.4.8 ../testable-parent testable-agent diff --git a/testable-all/pom.xml b/testable-all/pom.xml index e70101a..889e044 100644 --- a/testable-all/pom.xml +++ b/testable-all/pom.xml @@ -6,7 +6,7 @@ com.alibaba.testable testable-parent - 0.4.7 + 0.4.8 ../testable-parent testable-all diff --git a/testable-core/pom.xml b/testable-core/pom.xml index d199447..1a34513 100644 --- a/testable-core/pom.xml +++ b/testable-core/pom.xml @@ -6,7 +6,7 @@ com.alibaba.testable testable-parent - 0.4.7 + 0.4.8 ../testable-parent testable-core diff --git a/testable-maven-plugin/pom.xml b/testable-maven-plugin/pom.xml index 16b4d3c..0e08156 100644 --- a/testable-maven-plugin/pom.xml +++ b/testable-maven-plugin/pom.xml @@ -6,7 +6,7 @@ com.alibaba.testable testable-parent - 0.4.7 + 0.4.8 ../testable-parent testable-maven-plugin diff --git a/testable-parent/pom.xml b/testable-parent/pom.xml index fe61848..36456bc 100644 --- a/testable-parent/pom.xml +++ b/testable-parent/pom.xml @@ -5,7 +5,7 @@ 4.0.0 com.alibaba.testable testable-parent - 0.4.7 + 0.4.8 pom testable-parent Unit test enhancement toolkit @@ -42,7 +42,7 @@ 1.6 1.6.8 3.6.0 - 0.4.7 + 0.4.8 diff --git a/testable-processor/pom.xml b/testable-processor/pom.xml index 4b547db..10e62fd 100644 --- a/testable-processor/pom.xml +++ b/testable-processor/pom.xml @@ -6,7 +6,7 @@ com.alibaba.testable testable-parent - 0.4.7 + 0.4.8 ../testable-parent testable-processor