18
15

More than 5 years have passed since last update.

WireMockをスタンドアローンで使うときの基本的なメモ

Posted at

概要

WireMockをスタンドアローンで使うときの基本的なメモです。大概のことは公式のドキュメントで説明されています。

環境

  • Windows 10 Professional
  • WireMock 2.20
  • curl

参考

準備

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!"というレスポンスを行います。

200_hello_world.json
{
  "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"を指定します。

200_hello_world.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ファイルを指定します。

200_hello_world_all.json
{
  "request": {
    "method": "GET",
    "url": "/greeting/world"
  },
  "response": {
    "status": 200,
    "bodyFileName": "hello_world.json",
    "headers": {
      "Content-Type": "application/json"
    }
  }
}

レスポンスしたいJSONを下記のように定義しました。

hello_world.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はこのマッピングファイルがテンプレート機能を利用することを宣言します。

200_get_item_by_id_template.json
{
  "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になります。

100.json
{
  "id": 100,
  "name": "りんご"
}

同様に__files/101.jsonは、/item/101というリクエストのときに読まれるjsonになります。

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
18
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
15