WireMockの紹介

1。概要

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

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

2.Mavenの依存関係

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

 com.github.tomakehurst wiremock 1.58 test 

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("//localhost:8080/baeldung"); HttpResponse httpResponse = httpClient.execute(request);

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

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; }

次のコードは、サーバーが予期されたURLへの要求を受け取り、クライアントに到着する応答が正確に送信されたものであることを確認します。

verify(getRequestedFor(urlEqualTo("/baeldung"))); assertEquals("Welcome to Baeldung!", stringResponse);

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

wireMockServer.stop();

4.JUnit管理対象サーバー

セクション3とは対照的に、このセクションでは、JUnitルールを使用したWireMockサーバーの使用法を示します。

4.1。サーバーのセットアップ

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

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

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

引数が指定されていない場合、サーバーポートはデフォルト値8080を取ります。サーバーホスト(デフォルトは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("//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; }

The stub's operations are verified by the testing code below:

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. Request Header Matching

Now we will demonstrate how to stub a REST API with the matching of headers. Let's start with the stub configuration:

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

Similar to the preceding subsection, we illustrate HTTP interaction using the HttpClient API, with help of the same helper methods:

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

The following verification and assertions confirm functions of the stub we created before:

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

4.4. Request Body Matching

The WireMock library can also be used to stub a REST API with body matching. Here is the configuration for a stub of this kind:

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)));

Now, it is time to create a StringEntity object that will be used as the body of a request:

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

The code above uses one of the conversion helper methods define before, convertInputStreamToString.

Here is content of the wiremock_intro.json file on the classpath:

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

HTTP requests and responses can be configured and executed as follows:

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

This is the testing code used to validate the stub:

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

4.5. Stub Priority

The previous subsections deal with situations where an HTTP request matches only a single stub. It would be more complicated if there is more than a match for a request. By default, the most recently added stub will take precedence in such a case. However, users are allowed to customize that behavior to take more control of WireMock stubs.

We will demonstrate operations of a WireMock server when a coming request matches two different stubs, with and without setting the priority level, at the same time. Both scenarios will use the following private helper method:

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

Firstly, configure two stubs without consideration of the priority level:

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

Next, create an HTTP client and execute a request using the helper method described right above:

HttpResponse httpResponse = generateClientAndReceiveResponseForPriorityTests();

The following code snippet verifies that the last configured stub is applied regardless of the one defined before when a request matches both of them:

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

Let's move on to stubs with priority levels being set, where a lower number represents a higher priority:

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)));

Creation and execution of an HTTP request:

HttpResponse httpResponse = generateClientAndReceiveResponseForPriorityTests();

The following code validates the effect of priority levels, where the first configured stub is applied instead of the last:

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

5. Conclusion

This tutorial introduced WireMock and how to set up as well as configure this library for testing of REST APIs using various techniques, including matching of URL, request headers and body.

すべての例とコードスニペットの実装は、GitHubプロジェクトにあります。