Mock 這個詞對于測試人員來說并不陌生,當我們要測試的接口 A 依賴接口 B ,可 B 無法滿足我們的測試需求時,需要 Mock 一下接口 B,來測試 A。當前端和服務端并行開發時,如果服務端接口還沒有開發好,前端同學也會 Mock 一下。
那 Mock 到底是什么?
維基百科:
在面向對象程序設計中,模擬對象(英語:mock object,也譯作模仿對象)是以可控的方式模擬真實對象行為的假的對象。程序員通常創造模擬對象來測試其他對象的行為,很類似汽車設計者使用碰撞測試假人來模擬車輛碰撞中人的動態行為。
注意這里的關鍵信息,以可控的方式,模擬真實對象行為,假的對象。
為什么要模擬呢?
一定是因為沒有辦法或者不需要用真實的服務,比如:
真實的對象還沒開發好,但你又急需測試;
真實的對象是第三方的(比如各種開放平臺),沒有提供聯調環境,或是不便聯調,或是搭建很麻煩;
真實的對象無法覆蓋你要的測試場景(比如網絡錯誤),而使用 Mock,你想要什么就可以模擬什么;
真實的對象速度很慢,而模擬的非常快;
等等。
這些情況下,模擬對象是一個非常好的解決方案,它可以讓你的測試不被阻斷,還能模擬出你想要的各種場景。
但模擬,不是真實,模擬是按照我們設定的劇本在走,是我們自己控制的,而真實的情況可能存在各種不確定性,所以不能完全相信 Mock。另外,Mock 是把真實對象模擬了一遍,如果真實對象改了,模擬對象也得跟著改,數量一多,維護起來也是十分的麻煩。
怎么 Mock ?
本文介紹我們團隊在實際的項目中遇到的 3 種 Mock 場景,以及我們的設計方案。
案例1. Mock HTTP:通過域名映射實現 Mock
項目背景
我們要測試一個 HTTP 接口,這個接口在服務內部的處理會因地區不同而存在差異,雖然對外提供的業務接口只有 1 個,但在服務內部,如果判斷是 A 地區就會去調用 A 地區的接口,B 地區會去調用 B 地區的接口,不同地區通過域名區分。
比如,要測的是登錄接口 test.com/login,到了內部處理時就會因不同的地區去調用不同接口:
A 地區會調用:test.a.com/login
B 地區會調用:test.b.com/login
C 地區會調用:test.c.com/login
......
如下所示:
為了便于測試,我們需要 Mock 各個地區的接口,應該怎么做呢?
設計方案
方案如下:
在「中臺」所在的服務器上,將調用 A 地區接口的域名通過 hosts 中的配置映射到 Mock 平臺的 IP。配置好以后,「中臺」調用 A 地區的接口時,請求都會轉發到 Mock 服務器上,然后我們就可以在 Mock 服務器上對具體的接口進行配置,定制返回信息;
需要 Mock 多個地區時,將對應域名加到 hosts 里映射即可。當然也可以 Mock 一個固定的域名,如 test.mock.com,然后每個地區的域名進行配置化(配置中心)。當我們要 Mock 某個地區時,只需將該地區的配置的域名改為 test.mock.com 即可,這樣就不用去修改 hosts 文件了。
這種方案的優點是:
沒有代碼侵入,域名可通過 hosts 進行配置,將不同的域名映射到 Mock 服務器;
配置簡單,沒有什么門檻;
缺點是:
依賴的數據需要我們自己來配置,這需要額外投入精力去研究被依賴服務的接口信息,還要維護 Mock 數據;
Mock 控制粒度比較粗。在無任何代碼侵入的前提下,比如在測試 A 地區的接口時,需將被調用的所有接口都進行 Mock,而不能只 Mock 其中幾個接口。
僅支持 Mock HTTP 請求。
案例2. Mock RPC:基于 AOP 實現 Mock
項目背景
這個項目對另外一個項目有強依賴,并且我們對這個 Mock 方案的要求是,除了能滿足我們自己的常規測試外,還要能提供給外部客戶進行快速對接、聯調,要能支持 HTTP 和 RPC(Dubbo)。
設計方案
為了滿足這個需求,我們開發了Mock SDK。
SDK 中包含幾個攔截器:
AbstractAspect類:是一個抽象切面攔截器,是其它攔截器的父類,提供了一些抽象方法讓子類實現,以及一些通用的方法。
ControllerAspect類:HTTP 接口攔截器,負責獲取接口的 URL、獲取全部請求頭、獲取全部請求參數、獲取全部請求體數據。
FacadeAspect類:Dubbo 接口攔截器,負責獲取方法名及其參數。
AnnotationsAspect類:注解切面攔截器,當 Java 類不在 client 下,但是需要 Mock 對應的方法時,可以在該方法前加上注解@Mock。
使用時只需:
在pom文件中引入 Mock SDK;
spring-scan-bean配置 Mock 的工具類,加載到 spring 上下文容器中;
設置 Mock 開關配置。開啟 Mock 模式時,默認會對所有controller中的接口、client中的 Dubbo 方法以及所有加了 Mock 注解的方法進行攔截。
方案如下:
這種方案的優點是:
支持 Mock HTTP,提供給客戶聯調測試時可在controller層進行 Mock,但不推薦這么做,客戶自己 Mock HTTP 接口會更靈活;
支持 Mock RPC,我們自己測試時可在client層進行 Mock;
Mock 粒度更細:支持按接口粒度進行 Mock,還支持單個 Java 方法添加注解來實現 Mock;
Mock 節點靈活:controller層、client層、或加了 Mock 注解的 Java 方法均可。
缺點是:
性能問題:在 Mock 開啟模式下,每次請求都會去判斷是否存在 Mock 對象,接口性能會有一定程度受影響。
Dubbo 接口目前只在client層做的切面,所以在 Mock 平臺配置返回值時,出參字段沒辦法從接口文檔中直接獲取,因為client層的出參字段與接口文檔的參數字段不完全一致。
存在代碼侵入。就算在 Mock 配置為關閉的情況下,仍會生成一個無邏輯的切面。
案例3. Mock Python:基于數據存儲中間件實現 Mock
項目背景
該項目也是需要對接多個區域,不同區域的接口存在很大差異,而且被測服務的末端是 Python 服務。另外一個重要的點是:該項目的測試數據非常有限且不可重復利用。
其實用「方案1」去 Mock 接口也是可以的,但:
需要花很多時間去預研 Mock 數據;
被依賴服務的接口加解密方式、調用鏈路差異很大;
配置成本過高:比如一個登錄功能,有些區域可能需要調 5 個接口,有些可能要 7 個接口才能實現;為了實現一個業務功能,往往需要配幾十個接口的 Mock。
因此在權衡了時間、資源、風險利弊之后,我們采取了新的 Mock 方案 —— 基于數據存儲中間件的 Mock,我們用的是 Redis。
設計方案
基于數據存儲中間件的 Mock 方案其實是在被測服務中加入 Mock 邏輯,當啟用 Mock 時,直接從 Redis 獲取數據,而不去請求真實的數據,這就實現了 Mock 的目的。
Mock 方法:
配置 Mock 開關,便于開啟和關閉;
在 Redis 中配置 Mock 對應的Key/Value;
優點:
無需額外搭建 Mock 平臺,研發投入成本低;
無需關注各區域接口差異,Mock 的數據格式統一;
配置和維護成本低,也可編寫腳本實現批量 Mock。
缺點:
業務代碼驗證不全,Python 服務的業務代碼是驗證不到的。所以,Mock 測試之后,還要用僅存的真實數據去驗證一遍。
存在代碼侵入。為實現 Mock 功能,存在非業務性邏輯。
總結
上述這 3 個案例就是我們在實際項目中遇到并實踐過的 Mock 方案,當然還有其他的方案,這需要結合項目的實際情況綜合評估風險、資源、利弊后再做選擇。本文只是提供了一些思路,希望對大家有所啟發。
審核編輯:黃飛
-
HTTP
+關注
關注
0文章
516瀏覽量
32284 -
數據存儲
+關注
關注
5文章
992瀏覽量
51542 -
服務端
+關注
關注
0文章
68瀏覽量
7172
原文標題:我們用到的3種Mock測試方案
文章出處:【微信號:TestinChina,微信公眾號:Testin云測】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
STM32的三種復位類型
STM32的三種boot模式介紹
SD-WAN三種不同場景的部署和實踐
測試工程師的三種分支
總結:伺服電機三種不同的控制方式介紹資料下載

Redis實現限流的三種方式分享
無人機測深的三種方法總結

評論