WireMockの紹介

1概要

  • WireMock ** は、Webサービスをスタブ化およびモックするためのライブラリです。実際のWebサービスと同じように接続できるHTTPサーバーを構築します。

WireMock サーバーが動作しているときは、期待値を設定し、サービスを呼び出して、その動作を確認できます。

2 Mavenの依存関係

WireMockライブラリを利用できるようにするには、POMに次の依存関係を含める必要があります。

<dependency>
    <groupId>com.github.tomakehurst</groupId>
    <artifactId>wiremock</artifactId>
    <version>1.58</version>
    <scope>test</scope>
</dependency>

3プログラム管理サーバー

このセクションでは、WireMockサーバーを手動で構成する方法について説明します。

すなわちJUnit自動設定のサポートなし。使い方は非常に単純なスタブで示されています。

3.1. サーバー設定

WireMockサーバーは次のようにインスタンス化できます。

WireMockServer wireMockServer = new WireMockServer(String host, int port);

引数が指定されていない場合、サーバーホストはデフォルトで localhost に、サーバーポートは 8080 になります。

その後、2つの簡単な方法でサーバーを起動および停止できます。

wireMockServer.start();

そして:

wireMockServer.stop();

** 3.2. 基本的な使い方

WireMockライブラリは最初に基本的な使用法によって実証されます、そこではそれ以上の設定なしで正確なURLのスタブが提供されます。サーバーインスタンスを作成しましょう。

WireMockServer wireMockServer = new WireMockServer();

WireMockサーバーは、クライアントが接続する前に稼働している必要があります。

wireMockServer.start();

その後、Webサービスはスタブされます。

configureFor("localhost", 8080);
stubFor(get(urlEqualTo("/baeldung")).willReturn(aResponse().withBody("Welcome to Baeldung!")));

このチュートリアルでは、Apache HttpClient APIを使用して、サーバーに接続しているクライアントを表します。

CloseableHttpClient httpClient = HttpClients.createDefault();

その後、リクエストが実行され、レスポンスがそれぞれ返されます。

HttpGet request = new HttpGet("http://localhost:8080/baeldung");
HttpResponse httpResponse = httpClient.execute(request);

ヘルパーメソッドを使用して、 httpResponse 変数を String に変換します。

String responseString = convertResponseToString(httpResponse);

その変換ヘルパーメソッドの実装は次のとおりです。

private String convertResponseToString(HttpResponse response) throws IOException {
    InputStream responseStream = response.getEntity().getContent();
    Scanner scanner = new Scanner(responseStream, "UTF-8");
    String responseString = scanner.useDelimiter("\\Z").next();
    scanner.close();
    return responseString;
}
verify(getRequestedFor(urlEqualTo("/baeldung")));
assertEquals("Welcome to Baeldung!", stringResponse);

最後に、WireMockサーバーを停止してシステムリソースを解放する必要があります。

wireMockServer.stop();

4 JUnit管理対象サーバー

セクション3とは対照的に、このセクションではJUnit Rule を使ってWireMockサーバーを使用する方法を説明します。

4.1. サーバー設定

WireMockサーバーは、 @ Rule アノテーションを使用してJUnitテストケースに統合できます。これによりJUnitはライフサイクルを管理し、各テストメソッドの前にサーバーを起動し、メソッドが戻った後にサーバーを停止することができます。

プログラム管理サーバーと同様に、JUnit管理のWireMockサーバーは、指定されたポート番号を持つJavaオブジェクトとして作成できます。

@Rule
public WireMockRule wireMockRule = new WireMockRule(int port);

引数が指定されていない場合、サーバーポートはデフォルト値の 8080 を使用します。 Options インターフェースを使用して、 localhost にデフォルト設定されているサーバーホスト、およびその他の構成を指定できます。

4.2. URLマッチング

WireMockRule インスタンスを設定した後、次のステップはスタブを設定することです。このサブセクションでは、正規表現を使用してサービスエンドポイントのRESTスタブを提供します。

stubFor(get(urlPathMatching("/baeldung/.** "))
  .willReturn(aResponse()
  .withStatus(200)
  .withHeader("Content-Type", "application/json")
  .withBody("\"testing-library\": \"WireMock\"")));

HTTPクライアントの作成、リクエストの実行、レスポンスの受信に移りましょう。

CloseableHttpClient httpClient = HttpClients.createDefault();
HttpGet request = new HttpGet("http://localhost:8080/baeldung/wiremock");
HttpResponse httpResponse = httpClient.execute(request);
String stringResponse = convertHttpResponseToString(httpResponse);

上記のコードスニペットは、変換ヘルパーメソッドを利用しています。

private String convertHttpResponseToString(HttpResponse httpResponse) throws IOException {
    InputStream inputStream = httpResponse.getEntity().getContent();
    return convertInputStreamToString(inputStream);
}

これはまた別のプライベートメソッドを利用します。

private String convertInputStreamToString(InputStream inputStream) {
    Scanner scanner = new Scanner(inputStream, "UTF-8");
    String string = scanner.useDelimiter("\\Z").next();
    scanner.close();
    return string;
}

スタブの動作は、以下のテストコードで検証されています。

verify(getRequestedFor(urlEqualTo("/baeldung/wiremock")));
assertEquals(200, httpResponse.getStatusLine().getStatusCode());
assertEquals("application/json", httpResponse.getFirstHeader("Content-Type").getValue());
assertEquals("\"testing-library\": \"WireMock\"", stringResponse);

4.3. ヘッダーマッチングの要求

それでは、ヘッダーのマッチングを使ってREST APIをスタブする方法を説明します。スタブ設定から始めましょう。

stubFor(get(urlPathEqualTo("/baeldung/wiremock"))
  .withHeader("Accept", matching("text/.** "))
  .willReturn(aResponse()
  .withStatus(503)
  .withHeader("Content-Type", "text/html")
  .withBody("!!! Service Unavailable !!!")));

前のサブセクションと同様に、同じヘルパーメソッドを使用して、HttpClient APIを使用したHTTPのやり取りを示します。

CloseableHttpClient httpClient = HttpClients.createDefault();
HttpGet request = new HttpGet("http://localhost:8080/baeldung/wiremock");
request.addHeader("Accept", "text/html");
HttpResponse httpResponse = httpClient.execute(request);
String stringResponse = convertHttpResponseToString(httpResponse);

以下の検証とアサーションは、以前に作成したスタブの機能を確認します。

verify(getRequestedFor(urlEqualTo("/baeldung/wiremock")));
assertEquals(503, httpResponse.getStatusLine().getStatusCode());
assertEquals("text/html", httpResponse.getFirstHeader("Content-Type").getValue());
assertEquals("!!! Service Unavailable !!!", stringResponse);

4.4. ボディマッチングをリクエストする

WireMockライブラリは、ボディマッチングを使用してREST APIをスタブ化するためにも使用できます。この種のスタブの設定は次のとおりです。

stubFor(post(urlEqualTo("/baeldung/wiremock"))
  .withHeader("Content-Type", equalTo("application/json"))
  .withRequestBody(containing("\"testing-library\": \"WireMock\""))
  .withRequestBody(containing("\"creator\": \"Tom Akehurst\""))
  .withRequestBody(containing("\"website\": \"wiremock.org\""))
  .willReturn(aResponse()
  .withStatus(200)));

それでは、リクエストのボディとして使用される StringEntity オブジェクトを作成しましょう。

InputStream jsonInputStream
  = this.getClass().getClassLoader().getResourceAsStream("wiremock__intro.json");
String jsonString = convertInputStreamToString(jsonInputStream);
StringEntity entity = new StringEntity(jsonString);

上記のコードは、 convertInputStreamToString の前に定義した変換ヘルパーメソッドの1つを使用します。

これはクラスパス上の wiremock intro.json__ファイルの内容です。

{
    "testing-library": "WireMock",
    "creator": "Tom Akehurst",
    "website": "wiremock.org"
}

HTTP要求と応答は、次のように構成して実行できます。

CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost request = new HttpPost("http://localhost:8080/baeldung/wiremock");
request.addHeader("Content-Type", "application/json");
request.setEntity(entity);
HttpResponse response = httpClient.execute(request);

これはスタブを検証するためのテストコードです。

verify(postRequestedFor(urlEqualTo("/baeldung/wiremock"))
  .withHeader("Content-Type", equalTo("application/json")));
assertEquals(200, response.getStatusLine().getStatusCode());

4.5. スタブプライオリティ

前のサブセクションでは、HTTPリクエストが単一のスタブだけに一致する状況を扱いました。要求に一致するものが複数ある場合、それはより複雑になります。デフォルトでは、そのような場合は最後に追加されたスタブが優先されます。ただし、WireMockスタブをさらに制御するために、ユーザーはその動作をカスタマイズすることができます。

次のリクエストが2つの異なるスタブに一致したときの優先順位レベルの設定の有無にかかわらず、WireMockサーバーの動作を実演します。どちらのシナリオでも、次のプライベートヘルパーメソッドを使用します。

private HttpResponse generateClientAndReceiveResponseForPriorityTests() throws IOException {
    CloseableHttpClient httpClient = HttpClients.createDefault();
    HttpGet request = new HttpGet("http://localhost:8080/baeldung/wiremock");
    request.addHeader("Accept", "text/xml");
    return httpClient.execute(request);
}

まず、優先順位を考慮せずに2つのスタブを設定します。

stubFor(get(urlPathMatching("/baeldung/.** "))
  .willReturn(aResponse()
  .withStatus(200)));
stubFor(get(urlPathEqualTo("/baeldung/wiremock"))
  .withHeader("Accept", matching("text/.** "))
  .willReturn(aResponse()
  .withStatus(503)));

次に、HTTPクライアントを作成し、上記のヘルパーメソッドを使用してリクエストを実行します。

HttpResponse httpResponse = generateClientAndReceiveResponseForPriorityTests();

次のコードスニペットは、リクエストが両方のリクエストに一致したときに、以前に定義されたスタブに関係なく、最後に設定されたスタブが適用されることを確認します。

verify(getRequestedFor(urlEqualTo("/baeldung/wiremock")));
assertEquals(503, httpResponse.getStatusLine().getStatusCode());

優先順位を設定したスタブに移りましょう。数字が小さいほど優先順位が高くなります。

stubFor(get(urlPathMatching("/baeldung/.** "))
  .atPriority(1)
  .willReturn(aResponse()
  .withStatus(200)));
stubFor(get(urlPathEqualTo("/baeldung/wiremock"))
  .atPriority(2)
  .withHeader("Accept", matching("text/.** "))
  .willReturn(aResponse()
  .withStatus(503)));

HTTPリクエストの作成と実行

HttpResponse httpResponse = generateClientAndReceiveResponseForPriorityTests();

次のコードは、最後の設定ではなく最初の設定スタブが適用されている場合の優先順位の効果を検証します。

verify(getRequestedFor(urlEqualTo("/baeldung/wiremock")));
assertEquals(200, httpResponse.getStatusLine().getStatusCode());

5結論

このチュートリアルでは、WireMockと、URLのマッチング、リクエストヘッダー、ボディなど、さまざまな手法を使用したREST APIのテスト用にこのライブラリを設定および構成する方法を紹介しました。

すべての例とコードスニペットの実装はhttps://github.com/eugenp/tutorials/tree/master/testing-modules/rest-testing[GitHubプロジェクト]にあります。