技術筆記 WireMock
測試工具

WireMock 技術手冊

API MockStub 規則Docker整合測試

WireMock 是一台會照你寫的規則回話的假 HTTP 伺服器。你把「什麼樣的請求該回什麼」寫成 JSON 丟給它,它就變成那個還沒做好、或是很難叫它出錯的下游服務。

為什麼要用它

解除耦合
後端 API 還沒完成時,前端與其他服務可以先照約定好的介面開發串接,不必等對方。
異常模擬
500 錯誤、逾時、網路不穩這些真實環境很難重現的情境,用一條規則就能穩定重現。
數據一致
固定的測試資料集,CI/CD 的自動化測試不會因為下游資料變動而時好時壞。
效能測試
用 fixedDelayMilliseconds 模擬慢速網路,觀察前端在高延遲下的實際行為。

實務上大多拿它做什麼

依我自己專案裡的使用情形估的比例,不是統計數字。

前端串接開發 40%
整合測試 (CI) 30%
異常情境模擬 20%
效能/延遲測試 10%
WireMock vs Mockito:Mockito 是 Unit Test 的 Mock 框架,在 JVM 記憶體裡把物件替換掉;WireMock 是 HTTP 層的 Mock,真的起一台伺服器讓你的程式用真實的網路呼叫打進去。兩者測的層級不同,是互補而不是取代——連線逾時、header 帶錯、序列化失敗這類問題只有後者測得出來。

Docker Compose 配置

把 ./wiremock 掛進容器的 /home/wiremock,它啟動時就會自己去讀底下的 mappings/。

docker-compose.yml yaml
services:
  wiremock:
    image: wiremock/wiremock:3
    container_name: wiremock
    ports:
      - "8080:8080"
    volumes:
      - ./wiremock:/home/wiremock
    command:
      - "--verbose"
      - "--global-response-templating"
--global-response-templating 打開之後,Response Body 可以用 Handlebars 語法動態插值(例如把請求的 query 參數原樣回填),回應就不必寫死。

建議的目錄結構

project-root/
wiremock/
mappings/ # 規則 JSON,容器啟動時自動載入
get-user.json
post-login.json
__files__/ # 大型 Response Body 放這裡
large-body.json
規則檔改完不需要重啟容器,呼叫 /__admin/mappings/reset 就會重新載入整個 mappings/。

Stub 規則長什麼樣

每條規則都分成 request(什麼樣的請求算命中)和 response(命中後回什麼)。點下面的場景看四種常見寫法。

GET /api/users/123
{
  "request": {
    "method": "GET",
    "url": "/api/users/123"
  },
  "response": {
    "status": 200,
    "headers": {
      "Content-Type": "application/json"
    },
    "jsonBody": {
      "id": 123,
      "name": "Mock User"
    }
  }
}
POST /api/login
{
  "request": {
    "method": "POST",
    "url": "/api/login",
    "bodyPatterns": [
      {
        "matchesJsonPath": "$.account"
      }
    ]
  },
  "response": {
    "status": 200,
    "fixedDelayMilliseconds": 2000,
    "jsonBody": {
      "token": "mock-token-xyz"
    }
  }
}
GET /api/broken
{
  "request": {
    "method": "GET",
    "url": "/api/broken"
  },
  "response": {
    "status": 500,
    "jsonBody": {
      "error": "Internal Server Error"
    }
  }
}
GET /api/search?q=keyword
{
  "request": {
    "method": "GET",
    "urlPath": "/api/search",
    "queryParameters": {
      "q": {
        "equalTo": "keyword"
      }
    }
  },
  "response": {
    "status": 200,
    "jsonBody": {
      "results": []
    }
  }
}
多條規則同時命中時,WireMock 依 priority 由小到大挑第一條(數字越小越優先,預設 5)。沒設 priority 又互相重疊,命中的是哪一條就不保證了——寫「例外情境」的規則時記得把它的 priority 調高。

該打哪個 URL

這是新手最常卡住的地方:同一台 WireMock,從容器內外看到的位址不一樣。

本機的 Postman、瀏覽器
http://localhost:8080 走的是 Docker 的 port mapping(8080:8080),從宿主機看過去就是 localhost。
Compose 內的其他容器
http://wiremock:8080 同一個 Compose network 裡用 service name 當主機名,由 Docker 內建 DNS 解析。
在容器裡用 localhost:8080 連不到 WireMock——localhost 指的是那個容器自己,不是宿主機,也不是隔壁的容器。徵狀通常是 Connection refused。

管理與排錯指令

看即時日誌
docker compose logs -f wiremock 最常用的一條。--verbose 開著時,沒對上的請求會印出它比對失敗在哪一項。
熱重載規則
curl -X POST http://localhost:8080/__admin/mappings/reset 改完 mappings/ 下的 JSON 後呼叫,不必重啟容器。
列出目前規則
curl http://localhost:8080/__admin/mappings 確認規則有沒有真的被載入——載入失敗多半是 JSON 格式錯了。
查最近的請求
curl http://localhost:8080/__admin/requests 對方說「我打了但沒回」時,先看這裡有沒有收到請求,再看它比對到哪條規則。