Mock Server實踐

jopen 9年前發布 | 44K 次閱讀 單元測試 Mock Server

背景

在美團服務端測試中,被測服務通常依賴于一系列的外部模塊,被測服務與外部模塊間通過REST API或是Thrift調用來進行通信。要對被測服務進行系統測試,一般做法是,部署好所有外部依賴模塊,由被測服務直接調用。然而有時被調用模塊尚未開 發完成,或者調用返回不好構造,這將影響被測系統的測試進度。為此我們需要開發樁模塊,用來模擬被調用模塊的行為。最簡單的方式是,對于每個外部模塊依 賴,都創建一套樁模塊。然而這樣的話,樁模塊服務將非常零散,不便于管理。Mock Server為解決這些問題而生,其提供配置request及相應response方式來實現通用樁服務。本文將專門針對REST API來進行介紹Mock Server的整體結構及應用案例。

Mock Server實踐

名詞解釋

  • Mock規則:定義REST API請求及相應模擬響應的一份描述。
  • Mock環境:根據請求來源IP來區分的Mock規則分組。Mock Server可以定義多套Mock環境,各套環境間相互隔離。同一個IP只能對應一個Mock環境,不同的IP可以對應同一個Mock環境。
  • </ul>

    整體結構

    Mock Server由web配置頁面Mock Admin及通用Mock Stub組成:Mock Admin提供了web UI配置頁面,可以增加/刪除請求來源IP到Mock環境的映射,可以對各套環境中的Mock規則進行CRUD操作;Mock Stub提供通用樁服務,對被測系統的各類REST API請求調用,返回預先定義好的模擬響應。為了提高樁服務的通吐,使得樁服務能在被測系統壓力測試中得到好的表現,我們開啟了5個樁服務,通過 Nginx做負載均衡。Mock Server的整體結構如下圖所示。

    Mock Server實踐

    數據存儲

    • 將請求來源IP到Mock環境名的映射存儲到mock-env.conf中,mock-env.conf的每一行定義了一條映射,如:
      192.168.3.68 閆帥的測試機環境
      這條映射表明來源是192.168.3.68的請求,使用Mock環境名為閆帥的測試機環境的Mock規則。
    • 將配置的Mock規則存放到<對應Mock環境名>.xml中,下面部分展示了Mock規則的存儲格式。
    • </ul>

      <configuration>
      ...
        <mock id="716add4f-33f7-49ac-abf3-fc617712ffea" name="test001" author="yanshuai">
          <request>
            <uri>/api/test/.*</uri>
            <method>GET|POST|PUT|DELETE</method>
            <parameters>
              <parameter name="name" value="test.*"/>
              ...
            </parameters>
            <headers>
              <header name="nb_deviceid" value="1E[0-9a-zA-Z]+"/>
              ...
            </headers>
          </request>
          <response delay="1000" real="false">
            <statusCode>200</statusCode>
            <format>application/json;charset=UTF-8</format>
            <customHeaders>
              ...
            </customHeaders>
            <body>{"name":"閆帥"}</body>
          </response>
        </mock>
      ...
      </configuration>

      Mock Stub

      當請求發送到Mock Stub時,Mock Stub會根據請求的來源IP找到對應的獨立環境名,然后根據獨立環境名獲取所有預定義的Mock規則,遍歷這些Mock規則,如果找到一條規則與接受到 的請求匹配,那么返回預定義的模擬響應。如果找不到規則匹配,那么返回404錯誤。其中,規則匹配是根據請求中的uri/method/headers /parameters/body是否與Mock規則中定義的對應字段正則匹配來定的。

      Mock Server實踐

      Mock Admin

      • 打開Mock Admin配置頁面,如果尚未映射來源IP地址到環境,則點擊環境列表導航鏈接,進入環境列表頁面,點擊添加,輸入源IP及環境名,點擊確定按鈕,實現源IP到所設環境的映射。
        Mock Server實踐
      • 點擊規則列表,規則列表頁面將默認羅列出default環境的所有Mock規則(如“語音登錄code獲取”規則)。重新選擇環境,可以羅列出所選環境中 的Mock規則。每個Mock規則都處于詳細信息展開的狀態。點擊“全部折疊”按鈕,將把所有的規則詳細信息給隱藏;點擊“全部展開”按鈕,將把所有的規 則詳細信息給展開。點擊“只顯示本人創建的規則”,將過濾得到mis賬戶用戶創建的規則。點擊“按創建時間排序”的開關按鈕,將實現Mock規則的升序/ 降序顯示。
        Mock Server實踐
      • 點擊導航欄的“新建規則”選項,可以創建一個Mock規則,需要填寫規則名稱、請求及響應,并選中環境。對于請求,需要填寫URL及勾選Method,如 果要求對于符合某種規則的請求才被Mock,則填寫對應的Headers/Parameters/Body Like,這些數據都是正則匹配的形式。對于響應,如果勾選了“返回真實響應”,則只需要關注延時(延時是指返回請求需要的sleep時間,單位是毫 秒)。此時需要將請求的URL地址給寫完整了,需要包含host(IP)及port,不能只是path。如果不勾選“返回真實響應”,則將返回模擬響應。 Status Code填寫返回碼,比如200,404;Format選擇返回數據的格式,比如json,html等;還可以返回自定義的Headers及響應的 Body。點擊新建按鈕以后,如果創建成功,則提示成功創建,并跳轉到規則列表頁面。
        Mock Server實踐
      • 對于一個創建好的Mock規則,可以點擊Action下拉菜單,進行操作。如果點擊“克隆”,則跳轉到“新建規則”頁面,并將克隆的Mock規則信息給填 充進去;點擊“編輯”,則跳轉到更新頁面,更新頁面填充了要編輯的Mock規則信息;點擊“刪除”,則彈出確認刪除對話框,點擊確定按鈕,將刪除此規則; 點擊取消按鈕,則取消刪除操作。如果此Mock規則處于詳細信息展開狀態,則可點擊折疊來隱藏詳細信息;如果處于詳細信息折疊狀態,則可點擊展開選項,將 顯示詳細信息。上移選項,可以將Mock規則上移一位;下移選項,可以將Mock規則下移一位。
        Mock Server實踐
      • </ul>

        使用方式

        1. 修改被測服務的HTTP依賴,將依賴的IP和端口分別設置為mock.ep.sankuai.com和80,并重啟被測服務;
        2. 創建Mock規則;
        3. 調用被測服務的API,被測服務將調用Mock服務;
        4. 刪除Mock規則(可選)。
        5. </ol>

          編程使用

          創建/刪除Mock規則,除了可通過Mock Admin頁面配置外,Mock Server還提供了SDK方式,用戶可以通過編碼來使用Mock Server。

          • 在Maven工程pom.xml中添加mock-client依賴
          • </ul>

            <dependency>
              <groupId>com.sankuai.meituan.ep.mockserver</groupId>
              <artifactId>mock-client</artifactId>
              <version>1.0.6</version>
            </dependency>

            • 創建/刪除Mock規則
            • </ul>

              // 構造Mock規則
              MockRule rule = new MockRule();
              rule.setMockName("test-" + System.currentTimeMillis()); // Mock name必須設置
              rule.setAuthor("yanshuai"); // author必須設置,設置為代碼編寫者的mis賬號前綴,比如lining03
              MockRequest mockRequest = new MockRequest();
              mockRequest.setUri("/api/test/" + System.currentTimeMillis()); // Mock請求的uri必須設置
              /**

              • Mock請求的方法必須設置
              • 如果只有GET請求,則寫成GET;
              • 如果有GET請求及PUT請求,則寫成GET|PUT;
              • 即用|分割請求方法,不能有空格。 / mockRequest.setMethod("POST|GET"); // 必要的話,設置Mock請求的匹配header List<MockRequestHeader> mockRequestHeaders = new ArrayList<MockRequestHeader>(); mockRequestHeaders.add(new MockRequestHeader("device", "android2.3")); mockRequest.setHeaders(mockRequestHeaders); // 必要的話,設置Mock請求的匹配參數 List<MockRequestParameter> mockRequestParameters = new ArrayList<MockRequestParameter>(); mockRequestParameters.add(new MockRequestParameter("wd", "123.")); mockRequestParameters.add(new MockRequestParameter("version", "v1")); mockRequest.setParameters(mockRequestParameters); rule.setMockRequest(mockRequest); MockResponse mockResponse = new MockResponse(); mockResponse.setDelay(1000L); // 設置Mock響應的延時 mockResponse.setStatusCode(200); // 設置Mock響應的狀態碼 /**
              • 設置Mock響應的格式
              • 如果是json返回,則為application/json;charset=UTF-8;
              • 如果是文本返回,則為text/plain:charset=UTF-8;
              • 如果是xml返回,則為text/xml;charset=UTF-8;
              • 如果是html返回,則為text/html;charset=UTF-8。 */ mockResponse.setFormat("application/json;charset=UTF-8"); List<MockResponseHeader> mockResponseHeaders = new ArrayList<MockResponseHeader>(); // 設置Mock響應的header mockResponseHeaders.add(new MockResponseHeader("customHeaderName", "customHeaderValue")); mockResponse.setMockResponseHeaders(mockResponseHeaders); mockResponse.setBody("{\"code\":200}"); // 設置Mock響應的body rule.setMockResponse(mockResponse);

              // 創建Mock規則 final MockClient client = new MockClient(); String id = client.addRule("default", rule); // default為環境名,如果使用別的環境,則填寫別的環境名

              // 調用被測服務的API,被測服務將調用Mock服務 // 省略調用代碼...

              // 刪除Mock規則 client.removeRule("default", id); // default為環境名,如果使用別的環境,則填寫別的環境名</pre>

              典型案例

              1. 相同Mock環境,同一接口,不同參數,可以有不同的Mock結果
                按照下圖,依次創建這兩條規則(順序相關),然后在default環境對應的機器上,訪問 http://mock.ep.sankuai.com/user/v1/info?token=fake ,返回{"code":401,"type":"sys_err_auth_fail","message":"invalid token"};訪問 http://mock.ep.sankuai.com/user/v1/info?token=other ,返回{"user": {"id": 29008301,"mobile": "15001245907","isBindedMobile": 1}}。
                Mock Server實踐 Mock Server實踐
              2. 真實請求延時Mock
                按照下圖創建規則,在閆帥的測試機環境對應的機器上,訪問 http://mock.ep.sankuai.com/api/v1/divisions ,將延遲5s返回城市列表json串。
                Mock Server實踐
              3. 不同Mock環境,完全相同的接口參數,可以有不同的Mock結果
                按照下圖創建規則,在閆帥的測試機環境對應的機器上,訪問 http://mock.ep.sankuai.com/cachier/paynotify 返回值是failure;在支付php環境對應的機器上,訪問 http://mock.ep.sankuai.com/cachier/paynotify 返回值是success。
                Mock Server實踐 Mock Server實踐
              4. </ol>

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!