最近栈长注意到阿里开源了自家的 Mock 工具:TestableMock,该工具号称最轻量、简单、舒适的 Mock 测试工具,功能十分强大,媲美 PowerMock,用法比 Mockito 还要简洁,还不挑框架,指哪换哪,一个 @MockMethod 注解打天下。。。

这么强大的么?栈长赶紧来体验一翻!

TestableMock 简介

TestableMock 开源地址:

https://github.com/alibaba/testable-mock

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 写了一段逻辑,同事直呼看不懂,你试试看。。

4.吊打 Tomcat ,Undertow 性能很炸!!

5.《Java开发手册(嵩山版)》最新发布,速速下载!

觉得不错,别忘了随手点赞+转发哦!

阿里 Mock 工具正式开源,干掉市面上所有 Mock 工具!的更多相关文章

  1. 阿里宣布Atlas正式开源:带你重返App开发的田园时代

    继Weex之后,阿里在移动技术领域又有开源大动作. 3月13日,手机淘宝安卓客户端容器化框架Atlas正式宣布开源(https://github.com/alibaba/atlas ).Atlas由阿 ...

  2. 小米正式开源 SQL 智能优化与改写工具 SOAR

    近日,小米正式宣布开源 SOAR. 截至今日,该项目已经获得了 350 个「star」以及 44 个「fork」(GitHub项目地址:https://github.com/XiaoMi/soar) ...

  3. 新一代 CI 持续集成工具 flow.ci 正式开源

    很高兴地宣布 flow.ci 在 Apache-2.0 协议下正式开源了.flow.ci 是国内首套开源持续集成(CI) 解决方案,帮助企业团队实现开发流程(build-test-deploy)自动化 ...

  4. 袋鼠云研发手记 | 数栈·开源:Github上400+Star的硬核分布式同步工具FlinkX

    作为一家创新驱动的科技公司,袋鼠云每年研发投入达数千万,公司80%员工都是技术人员,袋鼠云产品家族包括企业级一站式数据中台PaaS数栈.交互式数据可视化大屏开发平台Easy[V]等产品也在迅速迭代.在 ...

  5. 开源一个Mac漂亮的小工具 PPRows for Mac, 在Mac上优雅的计算你写了多少行代码

    开源一个Mac漂亮的小工具 PPRows for Mac, 在Mac上优雅的计算你写了多少行代码. 开源地址: https://github.com/jkpang/PPRows

  6. 写了个汉字转G代码工具,无描边的那种,市面上没有类似的小软件

    学了不少G代码知识, 将公司废旧的三轴非标设备改造成了一个雕刻机,市面上的小软件不好用 网上下的软件有描边的,字体刻起来太粗,这个比较好用,看图应该都能明白吧, 就自己写了个,“少于150字的随笔不允 ...

  7. 如约而至:微信自用的移动端IM网络层跨平台组件库Mars已正式开源

    1.前言 关于微信内部正在使用的网络层封装库Mars开源的消息,1个多月前就已满天飞(参见<微信Mars:微信内部正在使用的网络层封装库,即将开源>),不过微信团队没有失约,微信Mars ...

  8. 【转】如约而至:微信自用的移动端IM网络层跨平台组件库Mars已正式开源

    网上看到关于微信官方的跨平台跨业务的终端基础组件Mars的介绍文章,转载这这里.源代码: https://github.com/Tencent/mars作者:男人链接:https://zhuanlan ...

  9. 重磅!阿里云Promtheus 正式免费公测

    每日头条 重磅!容器集群监控利器 阿里云Promtheus 正式免费公测 Prometheus 作为容器生态下集群监控的首选方案,是一套开源的系统监控报警框架.2019 年7月3日,阿里云Promth ...

随机推荐

  1. 微信小程序手机号解密失败-43001

    今天是2020年1月16号,从昨天下午开始,一直遇到一个问题: 客户在注册会员的时候的第二步,验证手机号的时候,一直提示验证失败,-43001 直接说原因:用户的session_key过期 期间大部分 ...

  2. Linq基础知识

    开发人员不需要关心将要访问的是关系数据库还是XML数据,或是远程对象,它都采用同样的访问方式. Linq包含一系列的查询技术,其中Linq到对象是对内存进行操作,LINQ到SQL是对数据库的操作,LI ...

  3. Abp小试牛刀之 图片上传

    图片上传是很常见的功能,里面有些固定的操作也可以沉淀下来. 本文记录使用Abp vNext做图片上传的姿势. 本文的技术核心与Abp无关,Abp只是手段! 目标 上传图片----->预览图片-- ...

  4. Azure Terraform(二)语法详解

    一,引言 上篇文章开始,我们简单介绍了以下通过基础设施管理工具----- Terraform,通过它来统一管理复杂的云基础设施资源.作为入门演示,使用Terraform 部署Azure 资源组的方式直 ...

  5. 事务的概念,以及事务在JDBC编程中处理事务的步骤

    事务是作为单个逻辑工作单元执行的一系列操作,一个逻辑工作单元必须有四个属性,称为原子性.一致性.隔离性和持久性 (ACID) 属性,只有这样才能成为一个事务 .JDBC处理事务有如下操作: 1,con ...

  6. 超级电容(Supercapacitor) 和电池的比较

    之前看到同事在电路设计里使用了超级电容来进行供电,好奇为什么没有用到普通的电池,于是就是找了找两个的区别.有篇文章讲得挺好,所以就直接翻译一下. 超级电容有点像普通电池和一般电容的结合体,能比一般的电 ...

  7. Flink学习之路(一)Flink简介

    一.什么是Flink? Apache Flink是一个面向分布式数据流处理和批量数据处理的开源计算平台,提供支持流处理和批处理两种类型应用的功能. 二.Flink特点 1.现有的开源计算方案,会把流处 ...

  8. wdCP V3.2

    wdCP是什么?关于wdCP更多的介绍,可看http://www.wdlinux.cn/wdcp/安装前先去体验下,看演示站吧http://www.wdlinux.cn/bbs/thread-5285 ...

  9. RMI之由浅入深(一)

    0x01.什么是RMI RMI(Remote Method Invocation)即Java远程方法调用,RMI用于构建分布式应用程序,RMI实现了Java程序之间跨JVM的远程通信.顾名思义,远程方 ...

  10. OpenTelemetry - 云原生下可观测性的新标准

    CNCF 简介 CNCF(Cloud Native Computing Foundation),中文为"云原生计算基金会",CNCF是Linux基金会旗下的基金会,可以理解为一个非 ...