unit-test-wiremock-rest-api について
外部 REST API 連携をネットワーク依存なしでテストするための WireMock スキルガイドです。レスポンスのスタブ化、リクエスト検証、タイムアウトやエラーのケースを扱います。
主な機能
- 01WireMock による HTTP レスポンスのスタブ化
- 02URL、ヘッダー、リクエストボディの照合
- 03クライアントが送信したリクエストの検証
- 04タイムアウトとエラーレスポンスのテスト
- 05競合を避ける動的ポートの使用
活用シーン
- 01サードパーティ REST API を呼び出すサービスのテスト
- 024xx、5xx、タイムアウトの再現
- 03リクエストパラメーターやヘッダー、本文の確認
- 04ネットワーク非依存テストの並列実行
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ giuseppe-trisciuoglio/ developer-kit --skill unit-test-wiremock-rest-apiインストール後、Claude Code で/unit-test-wiremock-rest-apiを入力して読み込まれたか確認します。
同梱ファイルreferences/advanced-examples.md
詳細
WireMock を使用した REST API のユニットテスト
概要
WireMock を使用して、外部 REST API との連携をテストするパターンです。レスポンスのスタブ化、リクエストの検証、エラーシナリオのテスト、ネットワークへの依存を排除した高速なテストを扱います。
使用する場面
- 外部 REST API を呼び出すサービスのテスト
- 予測可能なテスト動作を実現するための HTTP レスポンスのスタブ化
- エラーシナリオ(タイムアウト、5xx エラー、不正な形式のレスポンス)のテスト
- リクエストの詳細(ヘッダー、クエリパラメーター、リクエストボディ)の検証
手順
- 依存関係を追加する:テストスコープに WireMock を追加します(Maven/Gradle)
- 拡張機能を登録する:
dynamicPort()を指定して@RegisterExtension WireMockExtensionを登録します - クライアントを設定する:ベース URL として
wireMock.getRuntimeInfo().getHttpBaseUrl()を使用します - レスポンスをスタブ化する:リクエストのマッチング(URL、ヘッダー、ボディ)を指定して
stubFor()を使用します - 実行してアサートする:サービスメソッドを呼び出し、AssertJ で結果を検証します
- リクエストを検証する:正しい API の使用を確認するために
verify()を使用します
スタブが一致しない場合:URL エンコーディングとヘッダー名を確認し、クエリパラメーターには urlEqualTo を使用します。
テストがハングする場合:HTTP クライアントで接続タイムアウトを設定し、タイムアウトをシミュレートするには withFixedDelay() を使用します。
ポートが競合する場合:常に wireMockConfig().dynamicPort() を使用します。
使用例
Maven の依存関係
<dependency>
<groupId>org.wiremock</groupId>
<artifactId>wiremock</artifactId>
<version>3.4.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency>
基本的なスタブ化と検証
import com.github.tomakehurst.wiremock.junit5.WireMockExtension;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
import static com.github.tomakehurst.wiremock.client.WireMock.*;
import static org.assertj.core.api.Assertions.assertThat;
class ExternalWeatherServiceTest {
@RegisterExtension
static WireMockExtension wireMock = WireMockExtension.newInstance()
.options(wireMockConfig().dynamicPort())
.build();
@Test
void shouldFetchWeatherDataFromExternalApi() {
wireMock.stubFor(get(urlEqualTo("/weather?city=London"))
.withHeader("Accept", containing("application/json"))
.willReturn(aResponse()
.withStatus(200)
.withHeader("Content-Type", "application/json")
.withBody("{\"city\":\"London\",\"temperature\":15,\"condition\":\"Cloudy\"}")));
String baseUrl = wireMock.getRuntimeInfo().getHttpBaseUrl();
WeatherApiClient client = new WeatherApiClient(baseUrl);
WeatherData weather = client.getWeather("London");
assertThat(weather.getCity()).isEqualTo("London");
assertThat(weather.getTemperature()).isEqualTo(15);
wireMock.verify(getRequestedFor(urlEqualTo("/weather?city=London"))
.withHeader("Accept", containing("application/json")));
}
}
エラーシナリオ、ボディの検証、タイムアウトのシミュレーション、状態を保持するテストについては、references/advanced-examples.md を参照してください。
ベストプラクティス
- 動的ポート:並列テスト実行時の競合を防ぎます
- リクエストの検証:クライアントが正しく API を使用していることを確認します
- エラーのテスト:タイムアウト、4xx、5xx のシナリオを網羅します
- 焦点を絞ったスタブ:テストごとに対象を 1 つにします
- 自動リセット:
@RegisterExtensionにより、テスト間で WireMock がリセットされます - 実際の API を呼び出さない:サードパーティーのエンドポイントは常にスタブ化します
制約と警告
- 動的ポートが必須:固定ポートは並列実行時に競合を引き起こします
- HTTPS のテスト:TLS 接続をテストする場合は、WireMock の TLS 設定を行います
- スタブの優先順位:より具体的なスタブが一般的なスタブより優先されます
- パフォーマンス:WireMock によってオーバーヘッドが発生します。テストを高速化するには、クライアント層でモックします
- API の変更:スタブを実際の API コントラクトと同期させます
参考資料
- WireMock のドキュメント
- WireMock スタブ化ガイド
references/advanced-examples.md- エラーシナリオ、ボディの検証、タイムアウト
コメント
Markdown 対応