最近栈长留神到阿里开源了自家的 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开发手册(嵩山版)》最新公布,速速下载!

感觉不错,别忘了顺手点赞+转发哦!