最近栈长留神到阿里开源了自家的 Mock 工具:TestableMock,该工具号称最轻量、简略、舒服的 Mock 测试工具,性能非常弱小,媲美 PowerMock,用法比 Mockito 还要简洁,还不挑框架,指哪换哪,一个 @MockMethod 注解打天下。。。
这么弱小的么?栈长连忙来体验一翻!
TestableMock 简介
TestableMock 开源地址:
https://github.com/alibaba/te…
TestableMock 在 2020 年 12 月开始开源,出自阿里云云效团队,次要想解决 Java 开发者在日常单元测试中常常遇到的痛点:
- 内部依赖 Mock 繁琐
- 公有办法难测试
- 无返回值办法难测试
- 简单参数难结构
它所承载的职责是“ 让 Java 没有难测的办法 ”,换种思路写 Mock,让单元测试更简略,这也是 TestableMock 名字的来历。
无需初始化,不挑测试框架,甭管要换的是公有办法、静态方法、构造方法还是其余任何类的任何办法,也甭管要换的对象是怎么创立的。
写好 Mock 定义,加个 @MockMethod 注解,所有通通搞定。
支流 Mock 工具比照
在 TestableMock 开源之前,目前市面上支流的 Mock 工具次要有:
- Mockito
- Spock
- PowerMock
- JMockit
- EasyMock
- ….
Mockito 应该是目前应用最多的 Mock 工具了,因为它应用足够简略,在 IntelliJ IDEA 和 Eclipse 开发工具上也都有专用的插件反对,但 Mock 性能相对来说还是较弱,不能笼罩所有利用场景。因为其应用的是动静代理技术,咱们都晓得,动静代理只能在办法前后盘绕,有肯定的局限性,所以 final 类型、静态方法、公有办法全都无奈笼罩到。
下面所列的支流的 Mock 工具也只有 PowerMock 在性能上可能与 TestableMock 持平,但 PowerMock 应用较为简单,而且因为应用的是自定义类加载器技术,所以也还会存在肯定的问题。
上面来看下具体比照:
工具 | 原理 | 最小 Mock 单元 | 被 Mock 办法限度 | 难度 | IDE 反对 |
---|---|---|---|---|---|
Mockito | 动静代理 | 类 | 不能 Mock 公有 / 动态和构造方法 | 较容易 | 很好 |
Spock | 动静代理 | 类 | 不能 Mock 公有 / 动态和构造方法 | 较简单 | 个别 |
PowerMock | 自定义类加载器 | 类 | 任何办法皆可 | 较简单 | 较好 |
JMockit | 运行时字节码批改 | 类 | 不能 Mock 构造方法 | 较简单 | 个别 |
TestableMock | 运行时字节码批改 | 办法 | 任何办法皆可 | 很容易 | 个别 |
TestableMock 和 JMockit 底层统一,应用的是 “ 运行时字节码批改 ” 技术,在单元测试启动时就扫描测试类和被测类的字节码,实现 Mock 办法的替换。
当初综合看来,阿里开源的 TestableMock 是最牛逼的了,这是要干掉市面上所有 Mock 工具!另外,关注公众号 Java 技术栈,在后盾回复:工具,能够获取我整顿的 Java 开发工具系列干货,十分齐全。
上手 TestableMock
在我的项目中的 pom.xml 文件中减少 testable 相干依赖及单元测试相干依赖和插件,残缺的配置如下:
<properties>
<testable.version>0.4.9</testable.version>
<junit.version>5.6.2</junit.version>
</properties>
<dependencies>
<dependency>
<groupId>com.alibaba.testable</groupId>
<artifactId>testable-all</artifactId>
<version>${testable.version}</version>
<scope>test</scope>
</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-surefire-plugin</artifactId>
<configuration>
<argLine>-javaagent:${settings.localRepository}/com/alibaba/testable/testable-agent/${testable.version}/testable-agent-${testable.version}.jar</argLine>
</configuration>
</plugin>
</plugins>
</build>
这里栈长以 Maven 为示例集成应用 TestableMock,Gradle 版本请参考官网文档。另外,关注公众号 Java 技术栈,在后盾回复:Maven,能够获取我整顿的 Maven 系列教程,十分齐全。
减少一个类,调用任意办法、成员办法、静态方法:
/**
* @from 公众号:Java 技术栈
* @author 栈长
*/
public class TestableMock {
/**
* 调用任意办法
*/
public String commonMethod() {return "www".trim() + "." + "javastack".substring(1) + "www.javastack.cn".startsWith(".com");
}
/**
* 调用成员、静态方法
*/
public String memberMethod(String s) {return "{ \"result\": \"" + innerMethod(s) + staticMethod() + "\"}";
}
private static String staticMethod() {return "WWW_JAVASTACK_CN";}
private String innerMethod(String website) {return "our website is:" + website;}
}
减少单元测试类:
import com.alibaba.testable.core.annotation.MockMethod;
import org.junit.jupiter.api.Test;
import static com.alibaba.testable.core.matcher.InvokeVerifier.verify;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* @author 栈长
* @from 公众号:Java 技术栈
*/
class TestableMockTest {private TestableMock testableMock = new TestableMock();
/**
* Mock 任意办法
* @return
*/
@MockMethod(targetClass = String.class)
private String trim() {return "http://www";}
@MockMethod(targetClass = String.class, targetMethod = "substring")
private String substr(int i) {return "javastack.cn_";}
@MockMethod(targetClass = String.class)
private boolean startsWith(String website) {return false;}
/**
* Mock 成员办法
* @param text
* @return
*/
@MockMethod(targetClass = TestableMock.class)
private String innerMethod(String text) {return "mock_" + text;}
/**
* Mock 静态方法
* @return
*/
@MockMethod(targetClass = TestableMock.class)
private String staticMethod() {return "_MOCK_JAVASTACK";}
@Test
void commonMethodTest() {assertEquals("http://www.javastack.cn_false", testableMock.commonMethod());
verify("trim").withTimes(1);
verify("substr").withTimes(1);
verify("startsWith").withTimes(1);
}
@Test
void memberMethodTest() {assertEquals("{ \"result\": \"mock_hello_MOCK_JAVASTACK\"}", testableMock.memberMethod("hello"));
verify("innerMethod").withTimes(1);
verify("staticMethod").withTimes(1);
verify("innerMethod").with("hello");
verify("staticMethod").with();}
}
在以上单元测试类中,以 @MockMethod 注解标识的办法都是 Mock 办法,Mock 了任意办法、成员办法、静态方法。
应用的确很简略,非常灵活,性能也的确比动静代理那种要弱小,一个 @MockMethod 注解走天下,能够扔掉其余的 Mock 工具了。
参考文档:
- https://github.com/alibaba/te…
- https://alibaba.github.io/tes…
版权申明:本文系公众号 “Java 技术栈 ” 原创,原创实属不易,转载、援用本文内容请注明出处,禁止剽窃、洗稿,请自重,尊重别人劳动成果和知识产权。
近期热文举荐:
1.Java 15 正式公布,14 个新个性,刷新你的认知!!
2. 终于靠开源我的项目弄到 IntelliJ IDEA 激活码了,真香!
3. 我用 Java 8 写了一段逻辑,共事直呼看不懂,你试试看。。
4. 吊打 Tomcat,Undertow 性能很炸!!
5.《Java 开发手册(嵩山版)》最新公布,速速下载!
感觉不错,别忘了顺手点赞 + 转发哦!