天天看點

阿裡 Mock 工具正式開源,幹掉市面上所有 Mock 工具!

最近棧長注意到阿裡開源了自家的 Mock 工具:TestableMock,該工具号稱最輕量、簡單、舒适的 Mock 測試工具,功能十分強大,媲美 PowerMock,用法比 Mockito 還要簡潔,還不挑架構,指哪換哪,一個 @MockMethod 注解打天下。。。

這麼強大的麼?棧長趕緊來體驗一翻!

TestableMock 簡介

TestableMock 開源位址:

https://github.com/alibaba/testable-mock
阿裡 Mock 工具正式開源,幹掉市面上所有 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 工具!

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 系列教程,非常齊全。

增加一個類,調用任意方法、成員方法、靜态方法:

阿裡 Mock 工具正式開源,幹掉市面上所有 Mock 工具!

增加單元測試類:

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://alibaba.github.io/testable-mock/

版權申明:本文系公衆号 "Java技術棧" 原創,原創實屬不易,轉載、引用本文内容請注明出處,禁止抄襲、洗稿,請自重,尊重他人勞動成果和知識産權。

近期熱文推薦:

1.Java 15 正式釋出, 14 個新特性,重新整理你的認知!!

2.終于靠開源項目弄到 IntelliJ IDEA 激活碼了,真香!

3.我用 Java 8 寫了一段邏輯,同僚直呼看不懂,你試試看。。

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

5.《Java開發手冊(嵩山版)》最新釋出,速速下載下傳!

覺得不錯,别忘了随手點贊+轉發哦!

阿裡 Mock 工具正式開源,幹掉市面上所有 Mock 工具!

繼續閱讀