使用 WireMock 在開發和測試中模擬 API 服務

在本地開發和測試期間,您的應用依賴於遠端 API 的情況相當常見。網路問題、速率限制,甚至 API 提供商的停機都可能阻礙您的進度。這會嚴重影響您的生產力,並使測試變得更具挑戰性。這時,WireMock 就派上用場了。

WireMock 是一個開源工具,可幫助開發人員建立一個模擬伺服器,模擬真實 API 的行為,為開發和測試提供一個受控的環境。

假設您同時擁有一個 API 和一個前端應用,並且想要測試前端與 API 的互動方式。使用 WireMock,您可以設定一個模擬伺服器來模擬 API 的響應,從而在不依賴實際 API 的情況下測試前端行為。當 API 仍在開發中,或者當您想在不影響實際 API 的情況下測試不同場景時,這尤其有用。WireMock 支援 HTTP 和 HTTPS 協議,並可以模擬各種響應場景,包括延遲、錯誤和不同的 HTTP 狀態碼。

在本指南中,您將學習如何:

  • 使用 Docker 啟動一個 WireMock 容器。
  • 在本地開發中使用模擬資料,而無需依賴外部 API
  • 在生產環境中使用即時 API 從 AccuWeather 獲取即時天氣資料。

在 Docker 中使用 WireMock

官方的 WireMock Docker 映象 提供了一種方便的方式來部署和管理 WireMock 例項。WireMock 適用於多種 CPU 架構,包括 amd64、armv7 和 armv8,確保與不同裝置和平臺的相容性。您可以在 WireMock 文件網站上了解有關 WireMock 獨立版的更多資訊。

先決條件

要跟隨本操作指南,需要滿足以下先決條件

啟動 WireMock

透過以下步驟啟動 WireMock 的快速演示

  1. 在本地克隆 GitHub 倉庫

    $ git clone https://github.com/dockersamples/wiremock-node-docker
    
  2. 導航到 wiremock-endpoint 目錄

    $ cd wiremock-node-docker/
    

    WireMock 充當您的後端將與之通訊以檢索資料的模擬 API。模擬 API 響應已在 mappings 目錄中為您建立。

  3. 在克隆的專案目錄的根目錄下執行以下命令,啟動 Compose 堆疊

    $ docker compose up -d
    

    稍後,應用程式將啟動並執行。

    Diagram showing the WireMock container running on Docker Desktop

    您可以透過選擇 wiremock-node-docker 容器來檢視日誌

    Diagram showing the logs of WireMock container running on Docker Desktop
  4. 測試模擬 API。

    $ curl https://:8080/api/v1/getWeather\?city\=Bengaluru
    

    它將返回以下包含模擬資料的預設響應

    {"city":"Bengaluru","temperature":27.1,"conditions":"Mostly cloudy","forecasts":[{"date":"2024-09-02T07:00:00+05:30","temperature":83,"conditions":"Partly sunny w/ t-storms"},{"date":"2024-09-03T07:00:00+05:30","temperature":83,"conditions":"Thunderstorms"},{"date":"2024-09-04T07:00:00+05:30","temperature":83,"conditions":"Intermittent clouds"},{"date":"2024-09-05T07:00:00+05:30","temperature":82,"conditions":"Dreary"},{"date":"2024-09-06T07:00:00+05:30","temperature":82,"conditions":"Dreary"}]}

    使用 WireMock,您可以使用對映檔案定義預設響應。對於此請求,模擬資料定義在 wiremock-endpoint/mappings/getWeather/getWeatherBengaluru.json 的 JSON 檔案中。

    有關存根預設響應的更多資訊,請參閱 WireMock 文件

在開發中使用 WireMock

既然您已經嘗試了 WireMock,讓我們在開發和測試中使用它。在此示例中,您將使用一個具有 Node.js 後端的示例應用程式。此應用堆疊具有以下配置

  • 本地開發環境:Node.js 後端和 WireMock 執行的上下文。
  • Node.js 後端:表示處理 HTTP 請求的後端應用程式。
  • 外部 AccuWeather API:獲取即時天氣資料的真實 API。
  • WireMock:在測試期間模擬 API 響應的模擬伺服器。它作為 Docker 容器執行。
Diagram showing the architecture of WireMock in development
  • 在開發中,Node.js 後端向 WireMock 傳送請求,而不是實際的 AccuWeather API。
  • 在生產環境中,它直接連線到即時的 AccuWeather API 以獲取真實資料。

在本地開發中使用模擬資料

讓我們設定一個 Node 應用程式,將請求傳送到 WireMock 容器,而不是實際的 AccuWeather API。

先決條件

按照以下步驟設定非容器化的 Node 應用程式

  1. 導航到 accuweather-api 目錄

    確保您位於 package.json 檔案所在的目錄中。

  2. 設定環境變數。

    開啟位於 accuweather-api/ 目錄下的 .env 檔案。刪除舊條目,並確保它只包含以下單行內容。

    API_ENDPOINT_BASE=https://:8080

    這將告訴您的 Node.js 應用程式使用 WireMock 伺服器進行 API 呼叫。

  3. 檢查應用程式入口點

    • 應用程式的主檔案是 index.js,位於 accuweather-api/src/api 目錄中。
    • 此檔案啟動了 getWeather.js 模組,這對您的 Node.js 應用程式至關重要。它使用 dotenv 包從 .env 檔案載入環境變數。
    • 根據 API_ENDPOINT_BASE 的值,應用程式將請求路由到 WireMock 伺服器 (https://:8080) 或 AccuWeather API。在此設定中,它使用 WireMock 伺服器。
    • 程式碼確保僅在應用程式不使用 WireMock 時才需要 ACCUWEATHER_API_KEY,從而提高效率並避免錯誤。
    require("dotenv").config();
    
    const express = require("express");
    const axios = require("axios");
    
    const router = express.Router();
    const API_ENDPOINT_BASE = process.env.API_ENDPOINT_BASE;
    const API_KEY = process.env.ACCUWEATHER_API_KEY;
    
    console.log('API_ENDPOINT_BASE:', API_ENDPOINT_BASE);  // Log after it's defined
    console.log('ACCUWEATHER_API_KEY is set:', !!API_KEY); // Log boolean instead of actual key
    
    if (!API_ENDPOINT_BASE) {
      throw new Error("API_ENDPOINT_BASE is not defined in environment variables");
    }
    
    // Only check for API key if not using WireMock
    if (API_ENDPOINT_BASE !== 'https://:8080' && !API_KEY) {
      throw new Error("ACCUWEATHER_API_KEY is not defined in environment variables");
    }
    // Function to fetch the location key for the city
    async function fetchLocationKey(townName) {
      const { data: locationData } = await
    axios.get(`${API_ENDPOINT_BASE}/locations/v1/cities/search`, {
        params: { q: townName, details: false, apikey: API_KEY },
      });
      return locationData[0]?.Key;
    }
  4. 啟動 Node 伺服器

    在啟動 Node 伺服器之前,請確保您已透過執行 npm install 安裝了 package.json 檔案中列出的節點包。

    npm install 
    npm run start
    

    您應該會看到以下輸出

    > express-api-starter@1.2.0 start
    > node src/index.js
    
    API_ENDPOINT_BASE: https://:8080
    ..
    Listening: https://:5001

    輸出表明您的 Node 應用程式已成功啟動。請保持此終端視窗開啟。

  5. 測試模擬的 API

    開啟一個新的終端視窗並執行以下命令來測試模擬的 API

    $ curl "https://:5001/api/v1/getWeather?city=Bengaluru"
    

    您應該會看到以下輸出

    {"city":"Bengaluru","temperature":27.1,"conditions":"Mostly cloudy","forecasts":[{"date":"2024-09-02T07:00:00+05:30","temperature":83,"conditions":"Partly sunny w/ t-storms"},{"date":"2024-09-03T07:00:00+05:30","temperature":83,"conditions":"Thunderstorms"},{"date":"2024-09-04T07:00:00+05:30","temperature":83,"conditions":"Intermittent clouds"},{"date":"2024-09-05T07:00:00+05:30","temperature":82,"conditions":"Dreary"},{"date":"2024-09-06T07:00:00+05:30","temperature":82,"conditions":"Dreary"}]}%

    這表明您的 Node.js 應用程式現在已成功將請求路由到 WireMock 容器並接收模擬的響應。

    您可能已經注意到,您正在嘗試使用 https://:5001 作為 URL,而不是埠 8080。這是因為您的 Node.js 應用程式正在埠 5001 上執行,並且它正在將請求路由到正在監聽埠 8080 的 WireMock 容器。

    提示

    在繼續下一步之前,請確保停止節點應用程式服務。

在生產環境中使用即時 API 從 AccuWeather 獲取即時天氣資料

要使用即時天氣資料增強您的 Node.js 應用程式,您可以無縫整合 AccuWeather API。本指南的這一部分將引導您完成設定非容器化 Node.js 應用程式並直接從 AccuWeather API 獲取天氣資訊的步驟。

  1. 建立 AccuWeather API 金鑰

    https://developer.accuweather.com/ 註冊一個免費的 AccuWeather 開發者帳戶。在您的帳戶中,透過選擇頂部導航選單上的 `MY APPS` 來建立一個新應用,以獲取您唯一的 API 金鑰。

    Diagram showing the AccuWeather Dashboard

    AccuWeather API 是一個提供即時天氣資料和預報的 Web API。開發人員可以使用此 API 將天氣資訊整合到他們的應用程式、網站或其他專案中。

  2. 將目錄更改為 accuweather-api

    $ cd accuweather-api
    
  3. 使用 .env 檔案設定您的 AccuWeather API 金鑰

    提示

    為防止衝突,請確保在修改 .env 檔案之前,刪除任何名為 API_ENDPOINT_BASEACCUWEATHER_API_KEY 的現有環境變數。

    在您的終端上執行以下命令

    unset API_ENDPOINT_BASE
    unset ACCUWEATHER_API_KEY
    

    是時候在 .env 檔案中設定環境變量了

    ACCUWEATHER_API_KEY=XXXXXX
    API_ENDPOINT_BASE=http://dataservice.accuweather.com

    確保使用正確的值填充 ACCUWEATHER_API_KEY

  4. 安裝依賴項

    執行以下命令安裝所需的軟體包

    $ npm install
    

    這將安裝您 package.json 檔案中列出的所有軟體包。這些軟體包對於專案正常執行至關重要。

    如果您遇到任何與已棄用軟體包相關的警告,在此演示中可以暫時忽略它們。

  5. 假設您的系統上沒有預先執行的 Node 伺服器,請繼續執行以下命令來啟動 Node 伺服器

    $ npm run start
    

    您應該會看到以下輸出

    > express-api-starter@1.2.0 start
    > node src/index.js
    
    API_ENDPOINT_BASE: http://dataservice.accuweather.com
    ACCUWEATHER_API_KEY is set: true 
    Listening: https://:5001

    請保持此終端視窗開啟。

  6. 執行 curl 命令向伺服器 URL 傳送 GET 請求。

    在新的終端視窗中,輸入以下命令

    $ curl "https://:5000/api/v1/getWeather?city=Bengaluru"
    

    透過執行該命令,您實質上是在告訴您的本地伺服器為您提供名為 `Bengaluru` 的城市的天氣資料。該請求專門針對 `/api/v1/getWeather` 端點,並且您提供了查詢引數 `city=Bengaluru`。一旦您執行該命令,伺服器就會處理此請求,獲取資料並將其作為響應返回,`curl` 會在您的終端中顯示該響應。

    從外部 AccuWeather API 獲取資料時,您正在與反映最新天氣狀況的即時資料進行互動。

回顧

本指南已引導您完成使用 Docker 設定 WireMock 的過程。您已經學會了如何建立存根來模擬 API 端點,從而使您能夠在不依賴外部服務的情況下開發和測試您的應用程式。透過使用 WireMock,您可以建立可靠且一致的測試環境,重現邊緣情況,並加快您的開發工作流程。