最近栈长留神到阿里开源了自家的 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开发手册(嵩山版)》最新公布,速速下载!
感觉不错,别忘了顺手点赞+转发哦!