Spring Cloud Contract WireMock

Spring Cloud Contract WireMock モジュールを使用すると、Spring Boot アプリケーションで WireMock [GitHub] (英語) を使用できます。詳細については、Spring Cloud Contract のリポジトリサンプルサブフォルダー [GitHub] (英語) を確認してください。

Tomcat を組み込みサーバーとして使用する Spring Boot アプリケーションがある場合 ( spring-boot-starter-web のデフォルト)、クラスパスに spring-cloud-starter-contract-stub-runner を追加し、テストで Wiremock を使用するために @AutoConfigureWireMock を追加できます。Wiremock はスタブサーバーとして実行され、Java API を使用するか、テストの一部として静的 JSON 宣言を使用してスタブの動作を登録できます。

別のポートでスタブサーバーを起動するには、(たとえば) @AutoConfigureWireMock(port=9999) を使用します。ランダムなポートの場合は、0 の値を使用します。スタブサーバーポートは、テストアプリケーションコンテキストで wiremock.server.port プロパティを使用してバインドできます。@AutoConfigureWireMock を使用すると、WiremockConfiguration 型の Bean がテストアプリケーションコンテキストに追加され、同じコンテキストを持つメソッドとクラスの間でキャッシュされます。Spring 結合テストについても同様です。また、WireMockServer 型の Bean をテストに挿入することもできます。登録された WireMock サーバーは、各テストクラスの後にリセットされます。ただし、各テストメソッドの後にリセットする必要がある場合は、wiremock.reset-mappings-after-each-test プロパティを true に設定します。

スタブを自動登録する

@AutoConfigureWireMock を使用すると、ファイルシステムまたはクラスパス (デフォルトでは file:src/test/resources/mappings) から WireMock JSON スタブが登録されます。アノテーションの stubs 属性を使用して場所をカスタマイズできます。これには、Ant スタイルのリソースパターンまたはディレクトリを使用できます。ディレクトリの場合は */.json が付加されます。次のコードは例を示しています。

@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureWireMock(stubs="classpath:/stubs")
public class WiremockImportApplicationTests {

	@Autowired
	private Service service;

	@Test
	public void contextLoads() throws Exception {
		assertThat(this.service.go()).isEqualTo("Hello World!");
	}

}
実際、WireMock は常に src/test/resources/mappings からのマッピングと stubs 属性のカスタムの場所を読み込みます。この動作を変更するには、このドキュメントの次のセクションで説明するように、ファイルルートを指定することもできます。
また、stubs ロケーションのマッピングは Wiremock の「デフォルトマッピング」の一部とみなされず、テスト中に com.github.tomakehurst.wiremock.client.WireMock.resetToDefaultMappings を呼び出しても、stubs ロケーションのマッピングは含まれません。ただし、org.springframework.cloud.contract.wiremock.WireMockTestExecutionListener は、すべてのテストクラスの後、およびオプションですべてのテストメソッド (wiremock.reset-mappings-after-each-test プロパティによって保護される) の後に、マッピング (スタブの場所からの追加を含む) をリセットします。

Spring Cloud Contract のデフォルトのスタブ jar を使用する場合、スタブは /META-INF/group-id/artifact-id/versions/mappings/ フォルダーに保存されます。その場所、すべての埋め込み JAR からのすべてのスタブを登録する場合は、次の構文を使用できます。

@AutoConfigureWireMock(port = 0, stubs = "classpath*:/META-INF...

ファイルを使用したスタブボディの指定

WireMock は、クラスパスまたはファイルシステム上のファイルからレスポンス本文を読み取ることができます。ファイルシステムの場合、JSON DSL で、レスポンスに (リテラルの) body ではなく bodyFileName があることがわかります。ファイルはルートディレクトリ (デフォルトでは src/test/resources/__files) を基準にして解決されます。この場所をカスタマイズするには、@AutoConfigureWireMock アノテーションの files 属性を親ディレクトリの場所 (つまり、__files はサブディレクトリ) に設定します。Spring リソース表記を使用して、file:…​ または classpath:…​ の場所を参照できます。汎用 URL はサポートされていません。値のリストを指定できます。この場合、WireMock は、レスポンス本文を見つける必要があるときに、存在する最初のファイルを解決します。

files ルートを構成すると、スタブの自動ロードにも影響します。スタブは、mappings というサブディレクトリ内のルートの場所から取得されるためです。
files の値は、stubs 属性から明示的にロードされたスタブには影響しません。

代替: JUnit ルールの使用

より従来的な WireMock エクスペリエンスを得るには、JUnit @Rules を使用してサーバーを起動および停止できます。これを行うには、次の例 (英語) に示すように、WireMockSpring コンビニエンスクラスを使用して Options インスタンスを取得します。

@ClassRule は、このクラスのすべてのメソッドが実行された後にサーバーがシャットダウンすることを意味します。

Rest テンプレートの緩和された SSL 検証

WireMock を使用すると、https URL プロトコルを使用して「安全な」サーバーをスタブできます。アプリケーションが統合テストでそのスタブサーバーに接続しようとすると、SSL 証明書が無効であることがわかります (自己インストールされた証明書に関する通常の問題)。多くの場合、最良のオプションは、http を使用するようにクライアントを再構成することです。それが不可能な場合は、SSL 検証エラーを無視する HTTP クライアントを構成するように Spring に依頼できます (もちろん、テストの場合にのみ実行してください)。

これを最小限の手間で行うには、次の例に示すように、アプリケーションで Spring Boot RestTemplateBuilder を使用する必要があります。

@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
	return builder.build();
}

RestTemplateBuilder が必要なのは、ビルダーを初期化するためにコールバックを介して渡されるため、その時点でクライアントで SSL 検証をセットアップできるためです。@AutoConfigureWireMock アノテーションまたはスタブランナーを使用する場合、これはテストで自動的に行われます。JUnit @Rule アプローチを使用する場合は、次の例に示すように、@AutoConfigureHttpClient アノテーションも追加する必要があります。

@RunWith(SpringRunner.class)
@SpringBootTest("app.baseUrl=https://localhost:6443")
@AutoConfigureHttpClient
public class WiremockHttpsServerApplicationTests {

	@ClassRule
	public static WireMockClassRule wiremock = new WireMockClassRule(
			WireMockSpring.options().httpsPort(6443));
...
}

spring-boot-starter-test を使用する場合、クラスパスに Apache HTTP クライアントがあり、それが RestTemplateBuilder によって選択され、SSL エラーを無視するように構成されます。デフォルトの java.net クライアントを使用する場合、アノテーションは必要ありません (ただし、害はありません)。現在、他のクライアントはサポートされていませんが、将来のリリースで追加される可能性があります。

カスタム RestTemplateBuilder を無効にするには、wiremock.rest-template-ssl-enabled プロパティを false に設定します。

WireMock および Spring MVC モック

Spring Cloud Contract は、JSON WireMock スタブを Spring MockRestServiceServer にロードできる便利なクラスを提供します。次のプロジェクト (英語) はそれを示しています。

baseUrl 値はすべてのモック呼び出しの前に追加され、stubs() メソッドは引数としてスタブパスリソースパターンを受け取ります。前の例では、/stubs/resource.json で定義されたスタブがモックサーバーにロードされます。RestTemplate が example.org/ (英語) にアクセスするように要求された場合、その URL で宣言されているレスポンスを取得します。複数のスタブパターンを指定でき、それぞれをディレクトリ (すべての .json の再帰的リストの場合)、固定ファイル名 (前の例のように)、または Ant スタイルのパターンにすることができます。JSON 形式は通常の WireMock 形式であり、WireMockWeb サイト (英語) で説明されています。

現在、Spring Cloud Contract Verifier は Tomcat、Jetty、Undertow を Spring Boot 組み込みサーバーとしてサポートしており、Wiremock 自体は Jetty (現在 9.2) の特定のバージョンを「ネイティブ」サポートしています。ネイティブ Jetty を使用するには、ネイティブ Wiremock 依存関係を追加し、Spring Boot コンテナー (存在する場合) を除外する必要があります。