Contents

使用 Wiremock 搭建 mockapi

在開發或測試時,後端 API 往往尚未完成或難以重現特定情境(如錯誤回應、逾時)。WireMock 是一套強大的 HTTP Mock Server,可讓你在不依賴真實後端的情況下模擬 API 回應,達到測試隔離的效果。

WireMock 的主要用途

  • 測試隔離:單元測試或整合測試時,不需要真實的外部服務
  • 模擬特定情境:模擬 500 錯誤、逾時、網路延遲等難以重現的場景
  • 前後端並行開發:前端開發者在後端 API 完成前就能串接 Mock API
  • Contract Testing:驗證 API 格式是否符合約定

啟動方式

方式一:Standalone JAR(最快速)

從官網下載 JAR 檔後直接執行:

1
java -jar wiremock-standalone-3.x.x.jar --port 8080

啟動後預設會在當前目錄建立 mappings/__files/ 資料夾。

方式二:Maven / Gradle 整合

適合整合進 JUnit 測試:

1
2
3
4
5
6
7
<!-- Maven -->
<dependency>
  <groupId>org.wiremock</groupId>
  <artifactId>wiremock</artifactId>
  <version>3.x.x</version>
  <scope>test</scope>
</dependency>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
@Rule
public WireMockRule wireMockRule = new WireMockRule(8080);

@Test
public void testGetUser() {
    stubFor(get(urlEqualTo("/api/user/1"))
        .willReturn(aResponse()
            .withStatus(200)
            .withHeader("Content-Type", "application/json")
            .withBody("{\"id\":1,\"name\":\"Alice\"}")));
    // 測試程式碼...
}

方式三:Docker

1
2
3
4
docker run -it --rm \
  -p 8080:8080 \
  -v $PWD/mappings:/home/wiremock/mappings \
  wiremock/wiremock:latest

Mapping JSON 格式

mappings/ 目錄下建立 JSON 檔案定義 Mock 規則,格式分為 request(匹配條件)和 response(回應內容):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
{
  "request": {
    "method": "GET",
    "url": "/api/user/1"
  },
  "response": {
    "status": 200,
    "headers": {
      "Content-Type": "application/json"
    },
    "body": "{\"id\": 1, \"name\": \"Alice\"}"
  }
}

也可以將 body 單獨放到 __files/ 目錄,用 bodyFileName 參照:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
{
  "request": {
    "method": "GET",
    "urlPathPattern": "/api/users/[0-9]+"
  },
  "response": {
    "status": 200,
    "bodyFileName": "user-response.json"
  }
}

Request 匹配條件

WireMock 支援多種匹配方式:

方式 說明 範例
url 完整路徑比對 /api/user/1
urlPattern 正規表達式 /api/users/[0-9]+
urlPathPattern 路徑正規(忽略 query string) /api/users/.*
queryParameters Query 參數比對 {"page": {"equalTo": "1"}}
headers Header 比對 {"Authorization": {"contains": "Bearer"}}
bodyPatterns Body 比對(JSON、正規) {"matchesJsonPath": "$.name"}

動態 Response(Handlebars Template)

啟動時加上 --global-response-templating 參數可啟用 Handlebars 模板,讓 response 動態帶入 request 的值:

1
java -jar wiremock-standalone-3.x.x.jar --global-response-templating

Mapping 範例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
{
  "request": {
    "method": "GET",
    "urlPathPattern": "/api/user/(?<id>[0-9]+)"
  },
  "response": {
    "status": 200,
    "body": "{\"id\": {{request.pathSegments.[2]}}, \"name\": \"User-{{request.pathSegments.[2]}}\"}"
  }
}

也可以使用 randomValuenow(當前時間)等 Helper 函數產生動態資料。

參考資料