概要
WireMockをスタンドアローンで使うときの基本的なメモです。大概のことは公式のドキュメントで説明されています。
環境
- Windows 10 Professional
- WireMock 2.20
- curl
参考
- WireMock
- [WireMock User Documentation] (http://wiremock.org/docs/)
準備
WireMockのGetting StartedページからStandaloneで実行できるjarファイルをダウンロードします。
この記事ではwiremock-standalone-2.20.0.jar
を利用しました。
プロジェクトルートとなるディレクトリを作成してその直下にjarを配置し、起動用と停止用のbatファイルを作成しました。
Project-Root/
|
+--- wiremock-standalone-2.20.0.jar
|
+--- startup.bat
+--- shutdown.bat
Startup
下記の内容でstartup.batファイルを作成します。起動するときはこのbatファイルを実行します。
java -jar .\wiremock-standalone-2.20.0.jar
起動オプションを確認するには--help
を付けて実行します。よく使いそうなオプションとしては次のものがありました。
option | description |
---|---|
--bind-address | The IP to listen connections |
--port | The port number for the server to listen on (default: 8080). 0 for dynamic port selection. |
--root-dir | Sets the root directory, under which mappings and __files reside. This defaults to the current directory. |
--verbose | Enable verbose logging to stdout |
Shutdown
下記の内容でshutdown.batファイルを作成します。停止するときはこのbatファイルを実行します。
停止するには下記のエンドポイントへpostするようです。この例ではcurlを利用しています。
curl -X POST --header "Content-Type: application/json" --header "Accept: application/json" "http://localhost:8080/__admin/shutdown"
Stubbing
リクエストに対してどのようなレスポンスを返すかをjson形式のファイルに記述します。デフォルトのファイルの作成場所は、jarファイルと同じディレクトリのmappings
というディレクトリになります。
jsonファイルの名前は任意です。
Project-Root/
|
+--- wiremock-standalone-2.20.0.jar
|
+--- startup.bat
+--- shutdown.bat
|
+--- mappings/
簡単なスタブの例
下記の内容で200_hello_world.json
というファイルをmappingsディレクトリに作成します。
Project-Root/
|
+--- mappings/
|
+--- 200_hello_world.json
このスタブは/greeting
へのGETリクエストに対して、テキストで"Hello World!"というレスポンスを行います。
{
"request": {
"method": "GET",
"url": "/greeting"
},
"response": {
"status": 200,
"body": "Hello world!",
"headers": {
"Content-Type": "text/plain"
}
}
}
curlでアクセスしてみます。
> curl -v http://localhost:8080/greeting
* Trying ::1...
* Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /greeting HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.46.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: text/plain
< Matched-Stub-Id: a2c6ba06-2187-4132-b11d-663e0a58f0e0
< Transfer-Encoding: chunked
< Server: Jetty(9.2.z-SNAPSHOT)
<
Hello world!* Connection #0 to host localhost left intact
レスポンスをJSON形式にする
jsonBodyにjsonを書き、Content-Typeに"application/json"を指定します。
{
"request": {
"method": "GET",
"url": "/greeting"
},
"response": {
"status": 200,
"jsonBody": {
"message": "Hello world!"
},
"headers": {
"Content-Type": "application/json"
}
}
}
curlでアクセスしてみます。
> curl -v http://localhost:8080/greeting
* Trying ::1...
* Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /greeting HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.46.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: application/json
< Matched-Stub-Id: 6548a90d-f190-4f81-b425-abe696af5a3b
< Transfer-Encoding: chunked
< Server: Jetty(9.2.z-SNAPSHOT)
<
{"message":"Hello world!"}* Connection #0 to host localhost left intact
レスポンスするJSONを別ファイルで管理する
レスポンスするJSONをマッピングファイルには書かず、別のファイルで管理することもできます。デフォルトのファイルの作成場所は、jarファイルと同じディレクトリの__files
というディレクトリになります。
この例ではレスポンスしたいJSONを__fils/hello_world.json
で作成しました。
Project-Root/
|
+--- __files
| |
| +--- hello_world.json
|
+--- mappings/
|
+--- 200_hello_world_all.json
bodyFileNameに読み込むjsonファイルを指定します。
{
"request": {
"method": "GET",
"url": "/greeting/world"
},
"response": {
"status": 200,
"bodyFileName": "hello_world.json",
"headers": {
"Content-Type": "application/json"
}
}
}
レスポンスしたいJSONを下記のように定義しました。
[
{
"lang": "ja",
"greeting": "こんにちは世界!"
},
{
"lang": "yi",
"greeting": "העלא וועלט!"
},
{
"lang": "zu",
"greeting": "Sawubona Mhlaba!"
},
{
"lang": "uz",
"greeting": "Salom Dunyo!"
},
{
"lang": "ur",
"greeting": "ہیلو دنیا!"
},
{
"lang": "ta",
"greeting": "ஹலோ உலகம்!"
},
{
"lang": "si",
"greeting": "හෙලෝ වර්ල්ඩ්!"
}
]
curlでアクセスしてみます。
> curl -v http://localhost:8080/greeting/world
* Trying ::1...
* Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /greeting/world HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.46.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: application/json
< Matched-Stub-Id: 584c6236-7b2e-400f-89a2-98cabd551455
< Transfer-Encoding: chunked
< Server: Jetty(9.2.z-SNAPSHOT)
<
[
{
"lang": "ja",
"greeting": "こんにちは世界!"
},
{
"lang": "yi",
"greeting": "העלא וועלט!"
},
{
"lang": "zu",
"greeting": "Sawubona Mhlaba!"
},
{
"lang": "uz",
"greeting": "Salom Dunyo!"
},
{
"lang": "ur",
"greeting": "ہیلو دنیا!"
},
{
"lang": "ta",
"greeting": "ஹலோ உலகம்!"
},
{
"lang": "si",
"greeting": "හෙලෝ වර්ල්ඩ්!"
}
]
* Connection #0 to host localhost left intact
マッピングファイルのディレクトリを指定する
マッピングファイルのディレクトリを変えたい場合は、WireMock起動時に--root-dir
オプションで指定します。
この例ではsystem_a
ディレクトリ下にあるマッピングファイルを利用するように指定しています。
java -jar .\wiremock-standalone-2.20.0.jar --root-dir .\system_a
Project-Root/
|
+--- wiremock-standalone-2.20.0.jar
|
+--- system_a/
| |
| +--- __files
| +--- mappings
|
+--- system_b
|
+--- __files
+--- mappings
Request Matching
URL matching
次のようなRest APIで{id}の部分に任意の数値をアイテムIDとして指定するリクエストに対してマッピングするには
curl -v http://localhost:8080/item/{id}
urlPattern
にマッチングする正規表現を指定します。この例ではidに3桁までの数値を指定すると下記のマッピングファイルに記述したJSONがレスポンスされます。
{
"request": {
"method": "GET",
"urlPattern": "/item/(\\d{1,3})"
},
"response": {
"status": 200,
"jsonBody": {
"id": 100,
"name": "りんご"
},
"headers": {
"Content-Type": "application/json"
}
}
}
この例だと4桁以上の数値を指定した場合は次のようなレスポンスが返り、リクエストにマッチするレスポンスがないことがわかります。
Request was not matched
=======================
-----------------------------------------------------------------------------------------------------------------------
| Closest stub | Request |
-----------------------------------------------------------------------------------------------------------------------
|
GET | GET
/item/(\d{1,3}) | /item/1000 <<<<< URL does not match
|
|
-----------------------------------------------------------------------------------------------------------------------
idに4桁以上の数値が指定されたときにHTTP Status 404を返すようにするには、次のようにpriority
を指定したマッピングファイルを作成します。
{
"priority": 10,
"request": {
"method": "GET",
"urlPattern": "/item/(\\d)*"
},
"response": {
"status": 404,
"jsonBody": {
"errorCode": 999,
"errorMessage": "アイテムは見つかりませんでした"
},
"headers": {
"Content-Type": "application/json"
}
}
}
curlでアクセスしてみます。
> curl -v http://localhost:8080/item/1001
* Trying ::1...
* Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /item/1001 HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.46.0
> Accept: */*
>
< HTTP/1.1 404 Not Found
< Content-Type: application/json
< Matched-Stub-Id: 0d9cf308-6452-4833-904e-6c62c7df4b60
< Transfer-Encoding: chunked
< Server: Jetty(9.2.z-SNAPSHOT)
<
{"errorCode":999,"errorMessage":"アイテムは見つかりませんでした"}* Connection #0 to host localhost left intact
idの値に応じたレスポンス
例えば、idが100のときと101のときでレスポンスするJSONを変えるにはテンプレート機能を利用することで実現できます。
テンプレート機能を有効にするにはWiremock起動時のオプションに--local-response-templating
を追加します。
下記のテンプレート機能を利用したマッピングファイルのポイントはbodyFileNameの{{request.path.[1]}}
と、transformers
です。
Wiremockのテンプレートエンジンはhandlebarsを利用していて{{request.path.[1]}}
はhandlebarsの記法になります。この記述の[1]は/item/{id}
というリクエストパスの{id}部分を表しています。([0]はitemです。)
なのでbodyFileNameの"{{request.path.[1]}}.json"は、テンプレートエンジンで解釈されると{id}.jsonとなります。
transformers
はこのマッピングファイルがテンプレート機能を利用することを宣言します。
{
"request": {
"method": "GET",
"urlPattern": "/item/(\\d)*"
},
"response": {
"status": 200,
"bodyFileName": "{{request.path.[1]}}.json",
"headers": {
"Content-Type": "application/json"
},
"transformers": [
"response-template"
]
}
}
__files/100.json
は、/item/100
というリクエストのときに読まれるjsonになります。
{
"id": 100,
"name": "りんご"
}
同様に__files/101.json
は、/item/101
というリクエストのときに読まれるjsonになります。
{
"id": 101,
"name": "みかん"
}
Wiremockで利用できるリクエスト属性には下記のものが定義されています。
request attributes |
---|
request.url |
request.requestLine.path |
request.requestLine.pathSegments.[<n>] |
request.requestLine.query.<key>.[<n>] |
request.requestLine.method |
request.requestLine.host |
request.requestLine.port |
request.requestLine.scheme |
request.requestLine.baseUrl |
request.headers.<key>.[<n>] |
request.cookies.<key>.[<n>] |
request.body |