api-hook,更輕量的介面測試工具

福祿網路技術團隊發表於2020-11-26

前言

在網站的開發過程中,介面聯調和測試是至關重要的一環,其直接影響產品的核心價值,而目前也有許多技術方案和工具加持,讓我們的開發測試工作更加便捷。介面作為資料傳輸的重要載體,資料格式和內容具有多樣性,從巨集觀的角度上看,分為成功和失敗,這兩種狀態又可以細分,例如失敗對應的狀態碼有5/4,不同的狀態碼代表的問題是不一樣的,都需要一一考慮,成功返回後,所有欄位返回結果又是排列組合形式,那麼問題就來了,是否能在條件容許的情況下快速覆蓋所有的場景呢,從技術的角度上講,問題不大,但是有時候成本卻有點高,那怎麼以一種低成本的方式快速實現呢,本文將圍繞這個問題展開討論,並嘗試提供一種解決方案。

現狀

前面說到了工作中遇到的介面測試場景,當然目前也有很多工具可以幫我們實現介面的測試,如使用廣泛的postman和fiddler等工具,功能強大,可安裝外掛或自定義指令碼,解決資料測試的問題,比如我們想要mock服務,參考https://learning.postman.com/docs/designing-and-developing-your-api/mocking-data/setting-up-mock/ 即可,網上也有很多使用教程,如果願意花些時間的話,一定能給工作帶來效率的提升,好吧,前提是你要花些時間。

api-hook優勢

1.開箱即用

有時候我只想簡單修改一下介面資料,但是需要我安裝軟體,找教程搗騰半天,時間花費了,效率卻降低了,api-hook引入專案中,通過簡單配置(真的很簡單)即可使用,所有操作所見即所得,沒有學習成本;

2.輕量方便

工具足夠輕量,不需要另起服務,不需要單獨維護,它就是你頁面的一部分而已,你可以像控制一個div一樣去控制它;

工具介紹

1.)工具演示

功能說明
圖片描述
【1】是介面攔截/mock的切換區域,【2】可以關閉api-hook工具皮膚,【3】是工具皮膚顯示/隱藏開關;
介面攔截
圖片描述
當工具皮膚可見且處於介面攔截模式下,所有發起ajax請求的介面返回頁面前都會被攔截,當前處於編輯的介面處於介面請求列表第一位置,且背景有斑馬線滾動動畫,如果後續有其他介面響應被捕獲,那麼新的攔截介面處於編輯等待的狀態,背景呈現淡藍色,有底部位移動畫提示。當介面編輯完成,點選【確定】後,處於編輯等待狀態的介面會自動切換成編輯模式,當然也可以自行切換。
介面mock
圖片描述
介面mock整合mockjs的功能,因此template配置可參考mockjs官網說明,這裡需要說明的是template欄位需要遵循JSON格式規範。

2.)環境要求

該工具採用react開發,適用的專案也要求使用react技術框架;此外,工具會攔截所有ajax請求,因此確保你使用的介面請求是通過ajax發出的。

3.)使用方式

安裝npm包
npm install api-hook

元件匯入
在專案入口檔案引入元件

import ApiHook from 'api-hook';

function App() {
    return (
        <div className="App">
            <Main />
            <ApiHook
                autoFilter
                defaultVisiable
                allowOrigins={['http://localhost:3000']}
            />
        </div>
    );
}
......
ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
  document.getElementById('root')
);

4.)其他說明

支援響應型別
介面的響應型別目前只支援text/json,因此介面如果是documentblobarraybuffer等型別,則工具不做處理;

元件引數

屬性 說明 預設值
autoFilter 是否預設攔截介面 false
defaultVisiable 工具皮膚是否預設可見 false
allowOrigins 容許開啟工具功能的站點,為陣列型別,只有配置此項,才能在專案中使用工具

研發介紹

1.)流程設計

工具提供了兩種模式,介面mock和介面攔截,不同的模式內部流程稍有不同,具體如下:
圖片描述
介面攔截模式下,所有需要被攔截的介面響應都會被api-hook劫持,而不會對請求流程做任何處理。在工具提供的介面上可以修改響應狀態碼和介面的具體內容,在介面mock模式下,就是通過mockjs實現資料的模擬,mockjs通過自定義MockXMLRequest代理所有匹配請求,實現資料的響應。

2.)XMLHttpRequest代理

由於需要修改XMLHttpRequest的預設行為,因此專案程式碼實際訪問的是其代理物件,在介面攔截/mock下,都是重寫XMLHttpRequest物件,具體實現通過ajax-hook和mockjs來實現,接下來我們探究一下其中原理;
ajax-hook
在介面攔截模式,通過ajax-hook提供介面代理XMLHttpRequest原生物件,監聽所有原生xhr物件屬性,確保ajax-hook回撥先執行,其次是ajax請求的回撥;

XMLHttpRequest = function () {
        var xhr = new window[realXhr];
        for (var attr in xhr) {
            var type = "";
            try {
                type = typeof xhr[attr]
            } catch (e) {
            }
            if (type === "function") {
                // hookAjax methods of xhr, such as `open`、`send` ...
                this[attr] = hookFunction(attr);
            } else {
                Object.defineProperty(this, attr, {
                    get: getterFactory(attr),
                    set: setterFactory(attr),
                    enumerable: true
                })
            }
        }
        ......
 }

mockjs
mockjs將原生XMLHttpRequest儲存在window._XMLHttpRequest屬性上,宣告一個MockXMLHttpRequest物件,該物件模擬了XMLHttpRequest的行為和方法,當我們使用Mock.mock(...)api時,執行window.XMLHttpRequest = XHR;這裡XHR就是MockXMLHttpRequest;

代理物件切換
工具在不同模式下,使用不同的代理物件,在切換攔截和mock的時候,需要執行重置原生XMLHttpRequest和初始化代理物件;

// mock模式
 registerMock() {
        unProxy(); // 解除ajax-hook代理
        const { mockList } = this.state;
        mockList.forEach(({ url, template }) =&gt; {
            Mock.mock(url, template); // mock註冊
        });
 }
// 攔截模式
 unRegisterMock() {
        if (window._XMLHttpRequest) { // mock代理,重置原生ajax物件
            window.XMLHttpRequest = window._XMLHttpRequest;
        }
        ajaxProxy(); // 啟用ajax-hook代理
 }

最後

該工具可供前端開發人員和測試人員使用,力求提供一種更便捷的方式去實現資料的個性化修改。此次只推出了基礎功能,後續還將加入更多新特性,本倉庫地址:https://github.com/lanpangzi-zkg/api-hook ,如果覺得還行就點個star吧,有問題歡迎交流。

福祿ICH·架構組 福袋

相關文章