前端mock小結

??我們都知道,在現在流行的“前后端分離”架構中,前后端的聯調,是一個不能避免的問題,特別是在項目稍微有點規模之后,“等接口”似乎成了前端開發者的一種常態。所以通常我們在不借助任何工具的情況下,進行前后端聯調大概會出現以下幾種尷尬的局面:

  • 前后端開發速度不一致,前端頁面寫好之后,必需要等待服務端的接口出來,才能有足夠的數據支撐UI的顯示。
  • 服務端接口不能滿足界面的需求時,要前端調用發現問題之后,反饋給服務端,然后服務端需要根據要求修改接口定義,重新部署,前端再重新調用。
  • 前端調用接口的操作成為了測試接口是否有bug的手段。

??以上的情況就造成了前后端聯調過程中最主要的問題,溝通成本,時間成本,服務重啟的成本加在一起,就是工期經常延后的原因。

一、解決前后端聯調的以往做法

??在以往的做法中,解決這個問題的辦法通常有兩種,一種前端做法,一種后端做法。
??前端的做法一般是在業務代碼里面先寫上假數據供頁面的顯示,等后端接口寫好之后,再將假數據注釋掉,改成接口調用,通常表現為以下的形式:

getData = (id) =>{
 return $.get('/api/user/' + id);
 //return new Promise((resolve, reject)=> {
 //  setTimeout(()=>{
 //    return resolve({
 //      data: {
 //        errcode: 0,
 //        data: {
 //          id: 1,
 //          name: 'tom'
 //        }
 //      }
 //    })
 //  }, 100)
 //})
}

可以看到,這樣的做法會在業務代碼里面產生非常多的冗余代碼,且在真實接口和假數據之間的切換非常不利于維護,前端開發者必須要記住在上線前,把所有的假數據注釋掉,切換成真實接口的調用。如果有很多接口都這樣做的話,這樣大大增加了開發者的工作量。
??后端的做法大多是先寫一套測試數據的接口供前端調用,等接口開發完成之后再切換過來。這樣無疑又增加了后端開發者的工作量, 而即便是這樣,當后端在寫正式接口的過程中,增刪或者修改了某一個字段,亦或是數據接口發生了改變,這樣都不能及時的更新到臨時的測試接口上,前端也無法得到及時的反饋,所以會造成前端邏輯處理的很多返工操作。
??這兩種方法,無論是哪一種,在實際的應用中都非常不方便,既影響了業務代碼,也增加了正常開發的工作量,所以前端開發者在開發的過程中一直在尋求一種mock的方法,能夠在開發的過程中,前后端實現完全分離的,彼此不受牽制。

二、mock的概念

??所謂mock,意思就是模擬,上面提到的前端開發者通常用寫在業務代碼里面的假數據代替還沒有開發完成的接口返回的數據的方法,其實就是對前端數據的一種mock方法,只是這種方法不是很方便。于是阿里巴巴的某大神就出品了一款功能非常全面的模擬數據生成的 JS 庫,也就是我們現在見到的mock.js,通過它我們可以使用簡單的語法模擬各類常見的數據。
??想要在代碼里面使用mock.js首先要進行npm安裝:npm install mockjs --save-dev,或者直接在script標簽中引用:<script src="http://mockjs.com/dist/mock.js"\></script\>,然后還需要了解一些mock.js的語法規則,這些規則都很簡單,這里就不介紹語法了,只是舉一個簡單的例子來表明mock.js對于生成模擬數據來說有多方便。比如現在頁面需要如下所示的一個數據結構,但是后端接口還沒有開發好,這個時候頁面的顯示就需要前端自己來模擬一些數據填充。

{
    "name": "BeJson",
    "links": [
        {
            "name": "Google",
            "url": "http://www.google.com"
        },
        {
            "name": "Baidu",
            "url": "http://www.baidu.com"
        },
        {
            "name": "SoSo",
            "url": "http://www.SoSo.com"
        }
    ]
}

??這樣看,如果全部手寫的話,好像工作量也不是很大。但是如果一旦其中的links數組需要有成百上千條數據的時候,前端開發者一條一條的寫,亦或是復制粘貼都變得非常不現實,所以這時候我們可以利用mock.js來寫這樣一個結構:

Mock.mock({
    "name": "@name",
    "links|100": [
        {
            "name": "@name",
            "url": "@url"
        }
    ]
})

如上面的代碼所示,links|100是mock.js的一個語法,表示的是給links數組里面創建100個對象,每個對象都包含name和url兩個屬性,這兩個屬性會通過@name和@url這兩個mock.js的規則,隨機生成名字和鏈接,當然,這里生成的name是一個隨機的英文名。這樣再也不需要自己手動復制粘貼改數據,只需要改一個地方就可以輕松的拿到任意條數據。關于mock.js的語法規則可以查看其官網http://mockjs.com
??有了mock.js之后,前端開發者的mock之路又前進了一步,至少在寫mock數據的時候更加方便了。其實更多時候的做法是,單獨用mock.js寫一個data.json的文件,然后在業務代碼里面切換真實接口請求和本地data.json文件請求,如下面的代碼所示:

getData = (id) =>{
    //return $.get('/api/user/' + id);
    return $.get('data.json');
}

??或者直接寫真實的接口,然后請求發出去的時候,利用fiddler或者charles等代理工具,將這個接口Map Local到本地的data.json文件,這樣就不用改動業務代碼,更加方便易操作。

三、常用的兩個開源前端mock工具

??mock.js的出現雖然已經簡化了前端工作量,但是依舊有很多問題,或者說它只解決了一部分問題。比如說:

  • 所有接口的mock規則都需要開發者手動定義;
  • 難以模擬出各種不同的網絡請求狀態;
  • 難以模擬出數據錯誤,或者空數據的狀態;
  • 不能模擬出根據不同請求參數,返回不同結果的情況;

??上面的最后三種狀態都是在前端界面的開發過程中都需要考慮到的情況,但是mock.js都比較難以做到,所以這個時候就出現了一些前端的mock工具。這些工具能夠確保前端在開發的過程中的模擬數據可控,且在使用之后不會對前端或者服務端的流程有任何影響,使得前后端有一個明確的分界點。常見的前端mock工具有RAP,YApi,NEI,EasyMock,Mock-API等,他們都是基于Mock.js來進行數據模擬的,并在此基礎上做了不同的擴展。

1.RAP

??RAP是阿里團隊出的一款WEB接口管理工具,幫助開發人員有效的管理接口文檔。它是一個企業級應用,包括阿里集團在內的三百五十多個企業都在使用RAP管理重要的接口文檔。
??下面是一張RAP的一張開發流程圖,其實這張圖也基本適用于所有使用mock工具的項目。

RAP開發流程圖

??從這張圖上我們可以看到,項目的最開始就要先制定接口,并利用mock工具將接口模擬出來,然后前后端分別進行開發,這時候前端是跟mock工具生成的mock數據進行交互的,而后端則開發與測試自己的接口是否正確。在前后端都開發完畢之后,后端再把真實接口部署出來,然后前端把把mock環境切到真實環境,進行聯調和測試。此時這個階段已經不是開發的階段了,而是開發之后的校驗階段,由此可以看到,利用mock工具,我們至少能在開發階段做到真正的前后端分離的狀態了 。
??回到RAP本身來說,它最大的特色莫過于它的GUI了,良好的可視化界面使得創建接口變的非常的容易。它編寫接口的時候只需要按照定好的接口文檔,在響應參數列表里面新建需要返回的參數就可以,它會根據你新建的參數,以及設定的參數類型和mock規則,自動生成對應的接口數據,非常的方便。RAP還有一個比較酷的地方就是他能根據用戶編寫的mock規則校驗真實接口的正確性,如果切換到真實的接口之后,返回的數據結構或者數據類型與在mock中填寫的規則不一樣,它會在瀏覽器控制臺打印出錯誤信息。
??雖然RAP的可視化界面使得mock操作變得非常簡單,很容易就能拿到數據,但是如果要在項目中用到這些數據的話,還是有一些限制的,RAP的使用是通過在項目中引入一行RAP插件代碼,利用這個插件來攔截發出去的請求,然后返回RAP模擬出來的數據,當要切換到真是接口測試的時候只需要改動插件代碼上的一個參數就可以了,但是遺憾的是現階段RAP插件的請求攔截只支持KISSY和jQuery,具體使用規則,可以查看其官方文檔RAP用戶手冊

tips:網上有大牛也提供了AngualrJS版的RAP插件,詳見:https://github.com/xiaomaojames/ng-rap

2.YApi

??YApi是去哪兒網移動架構組開發的一個開源項目,可以幫開發者輕松創建發布,維護API,相比較RAP,它有以下優點:
??(1)YApi具有扁平化的權限設計,可以滿足大型企業級的項目管理,在YApi里超級管理員擁有最高權限,并將權限分配給若干組長,超級管理員只需管理組長,組長又分為分組組長與項目組長,分組組長在創建項目時可以指定項目組長,項目組長可以邀請組員參與項目,共享接口數據。
??(2)YApi在新建項目的時候,還可以快速導入其他格式的接口數據,方便快速添加接口。目前支持postman,swagger,har數據導入。當然首先你需要先在以上三個接口管理平臺上導出接口數據,然后再將導出的數據導入到YApi平臺上,它會自動解析文件,并生成相應的接口。以導入swagger數據為例:首先要生成 JSON 語言編寫的 Swagger API 文檔文件,例如這樣的數據http://petstore.swagger.io/v2/swagger.json,我們可以將其內容復制到 一個JSON 文件中,然后打開yapi平臺,進入到項目頁面,點擊數據管理,選擇相應的分組和swagger導入方式,選擇剛才的文件,就可以開始導入JSON數據,最后會生成相應的接口。這個功能比較適合一些成熟的接口,這些接口從一些接口平臺導出之后不會再變更的情況下會很方便,同時也適合一些項目的遷移。
??(3)YApi具有接口文檔管理的功能,在傳統后端的接口開發過程中,接口開發和接口測試是必不可少的,但是接口文檔因為沒有跟開發和測試聯系到一起,所以一旦在開發或者測試的過程中有改動,那么維護接口文檔將是一件很繁瑣的事情。YApi將接口文檔和測試通過單一數據源連接到一起,如果接口改動,因為改的是單一數據源,就不會出現更新不及時的情況,并且YApi的模擬接口還可以關聯接口文檔,所以當后端在開發的過程中調整了接口文檔中的定義時,前端開發者就能及時作出改動。

??YApi在一定程度上來說,比RAP的功能更加完善,也更加強大,它提供接口文檔管理,接口數據模擬(Mock),接口調試,自動化測試等一系列功能。
??雖然如此,然而最厲害的不一定是最合適的,在數金,我們通常使用swagger來管理接口,雖然YApi支持導出swagger格式的數據,并解析成mock接口,但是它是通過將swagger文檔導出成json格式的文件之后,再將這個文件解析出來,這樣就會產生一個問題,當后端同學改動了swagger上的現有接口,亦或是又增加了一些接口,就需要再重新導出一份swagger文檔的json文件,然后再導入YApi平臺解析一次,這樣的操作既冗雜又繁瑣,所以對于我們使用swagger來管理接口的團隊來說,如果某個mock工具能夠有“一鍵同步swagger”的操作,那將會是減輕不少的工作量。巧合的是,Easy Mock剛好能解決我們這個問題。

四、Easy Mock的介紹

??Easy Mock是大搜車前端團隊開發的一個可視化,能快速生成模擬數據的在線mock服務,他沒有RAP那么有限制性,也沒有YApi那么完善的功能,但是對于我們來說,它剛剛好,在對比了現有的幾種前端開源mock工具后,我們決定選用Easy Mock作為我們團隊的前端模擬工具,并將它部署在內網。
??與其他的mock工具一樣,Easy Mock基于Mock.js,能夠使用簡單的語法創建出模擬數據,如果你還不了解mock.js的語法,可以訪問其官網http://mockjs.com,除了支持mock.js的基本語法之外,Easy Mock還做了一些擴展,例如:

1.支持簡單的Function,可以實現邏輯判斷,并對結果進行動態的返回。
2.Easy Mock在每個mock接口里面注入了一些express的變量,這些變量就是原來 req 上的幾乎所有的屬性,如_req.header、_req.query等,有了這些變量,就可以根據用戶調用mock接口時傳進來的一些信息做非常動態寫響應式返回。
3.Easy Mock支持restful風格的接口,例如“/merchandise/:id”,我們可以通過_req.params.id 來獲取到參數的值。

??除了在mock.js語法的基礎上做了擴展之外,Easy Mock的另一大優勢是可以根據swagger中定義的實體的屬性類型生成對應的mock數據。由于我們公司大多使用swagger來管理接口,所以在定義好接口之后,可以先利用接口文檔部署一套只有數據結構,沒有真正實現功能的swagger接口,然后通過swagger文檔地址,就可以在Easy Mock中生成一個包含此文檔地址數據的模擬接口,此操作支持swagger1.0和swagger2.0的語法。
??由于我們在生成的過程中填入的是一個swagger文檔的地址,不是一個靜態的json文件,所以當swagger的接口有更新的時候,Easy Mock支持“一鍵同步”,且這個同步是智能的,它會先檢測這個接口是否有變動,如果有則對這個接口做覆蓋式的更新,如果沒有,則不會更新。這一特性對于不斷有需求進來,不斷迭代的項目組非常的友好,這也是我們選擇這個工具的非常重要的一個原因。
??通過Easy Mock來進行數據模擬對流程不會產生任何影響,只是通過swagger接口文檔來生成模擬接口,需要swagger注解做的更加嚴謹和完善,這樣在mock接口中才能看到更加清晰的這個接口的功能,用法等等信息。

Easy Mock的使用方法
??下面我們簡單的講一下Easy Mock的使用方法,以使用swagger的項目為例。如果你沒有在內網部署的話,可以進官網,注冊一個賬號,然后開啟你的神奇的swagger+Easy Mock之旅,新注冊的賬號會自動生成一個演示項目,里面創建了多種的Mock類型,對于新手來說,可以先看一下這個演示項目,在此基礎上進行編輯。如果你想創建自己的項目,可以跟著以下的步驟來做:
(1)創建項目
??點擊主頁右下角的藍色加號按鈕,進入項目創建界面

創建項目

(2)填寫基本信息
??因為我們要基于swagger來創建這個項目,所以注意要在swagger Docs Api里面填入你項目的swagger Docs Api的地址(不用swagger的可以跳過填swagger Docs Api這一欄)。

填寫基本信息

??注意:項目swagger Docs Api的地址并不是項目swagger的地址,一個通用的獲取swagger Docs Api地址的方法就是,將swagger的URL中項目名只有的部分替換成/v2/api-docs,比如地址為https://xxxx.xxxx.com/projectname/swagger-ui.html替換后的地址為https://xxxx.xxxx.com/projectname/v2/api-docs,這樣就能得到swagger Docs Api的地址了。
??基本信息填寫完畢后,點擊創建按鈕,即可創建成功。接下來回到項目頁面就可以看到我們創建的項目

創建成功

(3)查看接口信息
??點擊上圖的項目地址,進去之后,你將看到Easy Mock將你swagger中的接口都拉下來了。

創建好的項目

??我們可以看到,上面甚至顯示了POST/GET方法,以及一些描述性的文字,這些內容的顯示要求寫接口的同學定義的更加嚴謹,swagger注解要寫的更加全面。
??在接口信息的最右邊有四個按鈕,分別是預覽,編輯,復制地址以及其他操作,點擊預覽按鈕我們可以看到這個接口生成的模擬數據,如果接口是get方法的話,你將會直接看到返回值,但如果是post方法的話,需要你先在右邊的輸入框里面先輸入你的請求參數,然后才能看到返回結果。
POST請求

POST請求

??因為我們現在并沒有寫請求參數與返回數據之間的關系,所以不出意外的話,隨便輸入什么值,都可以得到一個模擬數據。
(4)根據需要完善接口
??我們必須要知道請求一個從Swagger上面拉下的模擬接口時,是不能直接根據請求入參來進行響應式的返回的(否則就不是模擬了),如果要定制化,則需要我們根據Easy Mock的擴展語法手動添加一些function來返回響應式數據,所以雖然模擬數據不能直接做到數據聯動,但是借助于響應式數據,也能玩出很多花樣。
??我們可以在數據編輯器中,為某個屬性指定一個function。在function中Easy Mock提供了_req對象,這個對象我們已經在上面提到過,它是express的一個對象,里面_req.header、_req.body等屬性,這使得我們可以通過這些屬性來做響應式數據,一個簡單的示例如下:

{
data:{
  default:'hah',
  _req:function({_req}){
    return _req
  },
  name:function({_req,Mock }){
    if(req.query.name === 'nk'){
      return _req.query.name + '_' +Mock.mock('@name')
    }else{
      return this.default
    }
  }
}

??除了響應式的返回,Easy Mock還支持自定義的響應狀態,通過在返回的結構中添加_res對象,可以給返回添加定制信息,_res對象里面包含_res.status,_res.cookies,_res.headers以及_res.data等,其中_res.data是在_res.status不為200的時候返回的,用來替代正常返回體里面的data。
??至此,我們運用以上簡單的四個步驟就可以基于swagger接口創建一個EasyMock的項目。如果swagger接口有更新的話,只需要點擊項目右上角的按鈕,就可以一鍵同步。
??項目創建好了之后,就到了使用的環節了,想要使用mock的接口,而不改變業務代碼的邏輯,則只需要在發請求的時候用代理工具,例如charles,fiddler等,將對應的請求Map Remote到我們的mock接口就可以了。

五、小結

??在前后端的聯調過程中,mock工具并不是必須存在的,甚至有很多同學覺得它的存在并沒有帶來任何價值,屬于“多此一舉”的操作,這本來就是很難界定其好與壞,或許對于一些小的項目來說,的確幫助沒有那么明顯,但是一旦項目比較繁瑣,那么前端接口mock將會給開發者帶來很多的便利:前端開發者不需要等待后端接口出來之后再調試頁面;前端開發者可以根據自己的意愿模擬出各種不同的返回結果來調整頁面的顯示等等都是顯而易見的便利。
??這里提供一個大搜車內部推薦的Easy Mock應用流程,可供大家在使用Easy Mock的過程中參考:

  • 需求,可行性評估
  • 需求評審,通常是交互稿或者原型
  • 交互或者設計評審,確認邏輯細節
  • 開發給出排期,包括(接口定義、前端開發、聯調、提測、測試時間)
  • PM或架構師系統和架構分析產出
  • 服務端設計數據庫和接口,給出詳細的接口定義
  • 接口評審,完成后部署開發服務器,會自動根據swagger定義通過easy-mock服務生產對應的mock項目。
  • 前后端分別開發,前端直接使用easy-mock提供的數據構建前端頁面。
  • 聯調,測試,運維發布。
    ??由于內網Easy Mock剛剛搭建好,我們團隊也是在這個過程中不斷的學習,所以如果大家在使用的過程中有發現任何問題或者疑問,希望可以及時與我們聯系,我們一定會盡快給大家答復。

六、其他工具

??最后,如果我們的工具,以及上面提到的RAP和YApi都不能滿足您的要求的話,您也可以訪問以下的鏈接來找到你心儀的工具:
NEI:網易的api接口管理平臺,功能很完善,但是不開源。
apizza:在線模擬調試,快速生成api文檔,導出離線版文檔,功能完善,不開源。
AMP:github的mock開源項目。
Mockbin:可以從HAR文件生成一個模擬樁。
Doclever:編寫REST接口文檔,版本控制,生成測試數據。
apiary:Powerful API Design Stack. Built for Developers。
mocky:無需登錄,直接生成一個resposne,url不固定。
mock-api:一個網絡服務,用來生成HTTP接口的模擬返回值。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容