LoginSignup
2
0

More than 3 years have passed since last update.

Spring Boot + WireMockでNoHttpResponseException

Last updated at Posted at 2019-07-30

事象

商用で動いているSpring BootのAppを改修した。
AppにはRestTemplateを使って他の連携先システムのREST APIを呼びにいく箇所があり、該当箇所を含む単体テストはWireMockでモックサーバを立てて実施していた。

改修に応じてテストを追加した所、既存のテストが突然
NoHttpResponseException:[server] failed to respond
などと例外を吐いてコケるようになった。

テストを単体で実行すると通り、通しで実行するとコケるという状態のため、テスト自体のミスでは無い模様。
ということで調査開始。

原因

WireMockへアクセスするAppのHttp Clientに、HttpURLConnectionを使用している場合に発生するバグらしい。

https://github.com/tomakehurst/wiremock/issues/97
SpringのRestTemplateも内部的にはHttpURLConnectionを使っているので該当。

対策

spring-cloud-contract-wiremockを使う。

https://github.com/tomakehurst/wiremock/issues/97
同issueに何種類かの対策が示されているので、お気に召すものを採用すれば良いと思われる。
一応の選定基準は以下の様な感じ。

  • Spring Bootのバージョンを上げる or HttpClientを変える
    商用で動いているAppなので、テストのために構成変更は基本NG→✕

  • HttpClientのconnection reuseを無効化
    設定場所が分からないし、Appの動作に影響出そう→✕

  • spring-cloud-contract-wiremockの利用
    テストのライブラリ変更だけで完結→○

spring-cloud-contract-wiremockは名前の通り内部でwireMockを利用しているので、テストコードの変更も最小限で済みました。
具体的には、サーバ設定の記法を変更して、既存のテスト用resourceのディレクトリを指定してやるだけ。
詳しい使い方は公式参照

Configuration(before)
public class ExampleUnitTest {
    @Rule
    public WireMockRule wireMockRule = new WireMockRule(8080);
.... 
Configuration(after)
@AutoConfigureWireMock(port = 8080, stubs = "classpath*:/META-INF/**/mappings/**/*.json")
public class ExampleUnitTest {
....

上記の通り、私の場合はstubs =で指定しているテスト用resourceのパスをよしなにしてやるだけで既存のテストコードがそのままパスするようになりました。

2
0
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
2
0