阿里 Mock 工具正式开源,干掉市面上所有 Mock 工具!
最近栈长注意到阿里开源了自家的 Mock 工具:TestableMock,该工具号称最轻量、简单、舒适的 Mock 测试工具,功能十分强大,媲美 PowerMock,用法比 Mockito 还要简洁,还不挑框架,指哪换哪,一个 @MockMethod 注解打天下。。。
这么强大的么?栈长赶紧来体验一翻!
TestableMock 简介
TestableMock 开源地址:

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 工具了。
参考文档:
版权申明:本文系公众号 "Java技术栈" 原创,原创实属不易,转载、引用本文内容请注明出处,禁止抄袭、洗稿,请自重,尊重他人劳动成果和知识产权。
近期热文推荐:
1.Java 15 正式发布, 14 个新特性,刷新你的认知!!
2.终于靠开源项目弄到 IntelliJ IDEA 激活码了,真香!
3.我用 Java 8 写了一段逻辑,同事直呼看不懂,你试试看。。
觉得不错,别忘了随手点赞+转发哦!
阿里 Mock 工具正式开源,干掉市面上所有 Mock 工具!的更多相关文章
- 阿里宣布Atlas正式开源:带你重返App开发的田园时代
继Weex之后,阿里在移动技术领域又有开源大动作. 3月13日,手机淘宝安卓客户端容器化框架Atlas正式宣布开源(https://github.com/alibaba/atlas ).Atlas由阿 ...
- 小米正式开源 SQL 智能优化与改写工具 SOAR
近日,小米正式宣布开源 SOAR. 截至今日,该项目已经获得了 350 个「star」以及 44 个「fork」(GitHub项目地址:https://github.com/XiaoMi/soar) ...
- 新一代 CI 持续集成工具 flow.ci 正式开源
很高兴地宣布 flow.ci 在 Apache-2.0 协议下正式开源了.flow.ci 是国内首套开源持续集成(CI) 解决方案,帮助企业团队实现开发流程(build-test-deploy)自动化 ...
- 袋鼠云研发手记 | 数栈·开源:Github上400+Star的硬核分布式同步工具FlinkX
作为一家创新驱动的科技公司,袋鼠云每年研发投入达数千万,公司80%员工都是技术人员,袋鼠云产品家族包括企业级一站式数据中台PaaS数栈.交互式数据可视化大屏开发平台Easy[V]等产品也在迅速迭代.在 ...
- 开源一个Mac漂亮的小工具 PPRows for Mac, 在Mac上优雅的计算你写了多少行代码
开源一个Mac漂亮的小工具 PPRows for Mac, 在Mac上优雅的计算你写了多少行代码. 开源地址: https://github.com/jkpang/PPRows
- 写了个汉字转G代码工具,无描边的那种,市面上没有类似的小软件
学了不少G代码知识, 将公司废旧的三轴非标设备改造成了一个雕刻机,市面上的小软件不好用 网上下的软件有描边的,字体刻起来太粗,这个比较好用,看图应该都能明白吧, 就自己写了个,“少于150字的随笔不允 ...
- 如约而至:微信自用的移动端IM网络层跨平台组件库Mars已正式开源
1.前言 关于微信内部正在使用的网络层封装库Mars开源的消息,1个多月前就已满天飞(参见<微信Mars:微信内部正在使用的网络层封装库,即将开源>),不过微信团队没有失约,微信Mars ...
- 【转】如约而至:微信自用的移动端IM网络层跨平台组件库Mars已正式开源
网上看到关于微信官方的跨平台跨业务的终端基础组件Mars的介绍文章,转载这这里.源代码: https://github.com/Tencent/mars作者:男人链接:https://zhuanlan ...
- 重磅!阿里云Promtheus 正式免费公测
每日头条 重磅!容器集群监控利器 阿里云Promtheus 正式免费公测 Prometheus 作为容器生态下集群监控的首选方案,是一套开源的系统监控报警框架.2019 年7月3日,阿里云Promth ...
随机推荐
- html中table表格标题固定表数据行出现滚动条
需求 web系统中有的用户不喜欢分页,希望数据能在一个页面中全部显示出来. 但是页面中是有滚动条的,当查看下面的数据时就不知道数据行中的列对应的是哪个标题的列. 也就是无法知道这个列是什么数据. 所以 ...
- .net MVC 微信公众号 点击菜单拉取消息时的事件推送
官方文档:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141016&token=&lang=zh_CN ...
- matplotlib学习日记(三)------简单统计图
(一)函数bar()---------绘制柱状图 import matplotlib as mpl import matplotlib.pyplot as plt mpl.rcParams[" ...
- idea中Server returns invalid timezone. Go to 'Advanced' tab and set 'serverTimezone' property manually.
我本机安装的mysql版本是5.7的,那么IDEA要连接mysql也应该匹配下驱动版本.把Driver改成MySQL for 5.1就可以了 在点击Test Connection测试下,成功啦!
- How to install android studio on ubuntu14.04
First: open the web page: https://developer.android.com/studio/index.html download the Android Studi ...
- C语言输入字符串
首先强调一点,C语言没有字符串的概念!所谓的字符串实际上还是以数组形式保存的. 方法1 -- 通过"%s"输入 优点:简单明了,输入字符只要不大于数组长度都可以. #includ ...
- MongoDb学习(四)--Repository----语法关键字
表7.查询方法支持的关键字 关键词 样品 逻辑结果 After findByBirthdateAfter(Date date) {"birthdate" : {"$gt& ...
- Java学习日报7.9
今日内容 阅读了构建之法第一章 工程师的宗旨:我构建,故我在. 哲学家的宗旨:我思,故我在. 科学家的宗旨:我发现故我在. 明天继续研究构建之法这本书!
- YourBatman 2020年感悟关键词:科比、裁员、管理层、活着
目录 本文提纲 ✍前言 版本约定 ✍正文 科比 裁员 如何避免被裁? 1.不要迷恋管理,一味追求"当官" 2.别以为裁员只裁一线,不裁管理层 3.即使步入管理,建议不要脱离技术 4 ...
- tail常用命令总结
tail命令作用: tail命令用途是依照要求将指定的文件的最后部分输出到标准设备,通常是终端,通俗讲来,就是把某个档案文件的最后几行显示到终端上,假设该档案有更新,tail会自己主动刷新,确保你看到 ...