対向先をモック化したテストを行いたいときにはよく WireMock を使用しています。
リクエストマッチングも行うことができ非常に便利です。
stubFor(post(urlEqualTo("/mockurl"))
.withRequestBody(equalToJson(REQUEST_JSON_STRING))
.willReturn(aResponse().withStatus(200).withHeader("Content-Type", "application/json")
.withBody(RESPONSE_JSON_STRING)));
上記のように書けば、REQUEST_JSON_STRING
に一致する JSON メッセージを受け付けた場合のみ、RESPONSE_JSON_STRING
を返却してくれます。
ところが、
- アプリでランダム文字列を発行している場合
- アプリで現在時刻を利用している場合
など、マッチングが難しい項目もよくあります。
{
"token": "uPx2bB9"
"accept_date": "2018-01-01T00:00:00.000Z",
}
また、REQUEST_JSON_STRING
をファイルから読み込みたい場合、可変項目の数だけファイルを用意するというのもやりたくありません。
こんなときは、equalToJson
に引数を追加します。
StringValuePattern com.github.tomakehurst.wiremock.client.WireMock.equalToJson(String value, boolean ignoreArrayOrder, boolean ignoreExtraElements)
ignoreExtraElements = true
とすることで、value
に存在しない要素は無視されます。
stubFor(post(urlEqualTo("/mockurl"))
.withRequestBody(equalToJson(REQUEST_JSON_STRING, true, true))
.willReturn(aResponse().withStatus(200).withHeader("Content-Type", "application/json")
.withBody(RESPONSE_JSON_STRING)));
上記のように設定しておけば、
REQUEST_JSON_STRING
:
{
"name": "hoge",
"data": {
"value": 1000
}
}
実際にきたリクエスト:
{
"name": "hoge",
"data": {
"token": "uPx2bB9",
"id": "abcde",
"value": 1000
}
}
でもマッチングに成功します(token
や id
の項目は無視される)。
さらに matchingJsonPath
を使えば、無視された項目の検証も可能です。
StringValuePattern com.github.tomakehurst.wiremock.client.WireMock.matchingJsonPath(String value)
要素が存在することを検証したい場合
(アプリで現在時刻やランダム文字列が発行され、比較が難しい場合など)
stubFor(post(urlEqualTo("/mockurl"))
.withRequestBody(equalToJson(REQUEST_JSON_STRING, true, true))
.withRequestBody(matchingJsonPath("$.data.token")) // "token" の項目があることを検証
.willReturn(aResponse().withStatus(200).withHeader("Content-Type", "application/json")
.withBody(RESPONSE_JSON_STRING)));
要素の値も検証したい場合
(テストデータに応じて可変な要素を検証したい場合など)
stubFor(post(urlEqualTo("/mockurl"))
.withRequestBody(equalToJson(REQUEST_JSON_STRING, true, true))
.withRequestBody(matchingJsonPath("$.data[?(@.id == 'abcde')]")) // "id" の値を検証
.willReturn(aResponse().withStatus(200).withHeader("Content-Type", "application/json")
.withBody(RESPONSE_JSON_STRING)));