共通のトップレベル要素

次のセクションでは、最も一般的なトップレベルの要素について説明します。

説明

description を契約に追加できます。説明は任意のテキストです。次のコードは例を示しています。

Groovy
			org.springframework.cloud.contract.spec.Contract.make {
				description('''
given:
	An input
when:
	Sth happens
then:
	Output
''')
			}
YAML
description: Some description
name: some name
priority: 8
ignored: true
request:
  url: /foo
  queryParameters:
    a: b
    b: c
  method: PUT
  headers:
    foo: bar
    fooReq: baz
  body:
    foo: bar
  matchers:
    body:
      - path: $.foo
        type: by_regex
        value: bar
    headers:
      - key: foo
        regex: bar
response:
  status: 200
  headers:
    foo2: bar
    foo3: foo33
    fooRes: baz
  body:
    foo2: bar
    foo3: baz
    nullValue: null
  matchers:
    body:
      - path: $.foo2
        type: by_regex
        value: bar
      - path: $.foo3
        type: by_command
        value: executeMe($it)
      - path: $.nullValue
        type: by_null
        value: null
    headers:
      - key: foo2
        regex: bar
      - key: foo3
        command: andMeToo($it)
Java
Contract.make(c -> {
	c.description("Some description");
}));
Kotlin
contract {
	description = """
given:
	An input
when:
	Sth happens
then:
	Output
"""
}

名前

契約の名前を指定できます。should register a user という名前を指定するとします。これを行うと、自動生成されたテストの名前は validate_should_register_a_user になります。また、WireMock スタブ内のスタブの名前は should_register_a_user.json です。

生成されたテストをコンパイルできなくなる文字が名前に含まれていないことを確認する必要があります。また、複数の契約に同じ名前を指定すると、自動生成されたテストはコンパイルに失敗し、生成されたスタブが相互にオーバーライドされることに注意してください。

次の例は、契約に名前を追加する方法を示しています。

Groovy
org.springframework.cloud.contract.spec.Contract.make {
	name("some_special_name")
}
YAML
name: some name
Java
Contract.make(c -> {
	c.name("some name");
}));
Kotlin
contract {
	name = "some_special_name"
}

契約の無視

契約を無視したい場合は、プラグイン設定で無視される契約の値を設定するか、契約自体に ignored プロパティを設定します。次の例は、その方法を示しています。

Groovy
org.springframework.cloud.contract.spec.Contract.make {
	ignored()
}
YAML
ignored: true
Java
Contract.make(c -> {
	c.ignored();
}));
Kotlin
contract {
	ignored = true
}

進行中の契約

進行中の契約では、プロデューサー側でテストは生成されませんが、スタブの生成は許可されます。

実際に実装を行わずにコンシューマーが使用するスタブを生成するため、誤検知が発生する可能性があるため、この機能は注意して使用してください。

進行中の契約を設定する場合、次の例はその方法を示しています。

Groovy
org.springframework.cloud.contract.spec.Contract.make {
	inProgress()
}
YAML
inProgress: true
Java
Contract.make(c -> {
	c.inProgress();
}));
Kotlin
contract {
	inProgress = true
}

failOnInProgress Spring Cloud Contract プラグインプロパティの値を設定して、進行中の契約が少なくとも 1 つソース内に残っているときにビルドが中断されるようにすることができます。

ファイルから値を渡す

バージョン 1.2.0 以降では、ファイルから値を渡すことができます。プロジェクトに次のリソースがあると仮定します。

└── src
    └── test
        └── resources
            └── contracts
                ├── readFromFile.groovy
                ├── request.json
                └── response.json

さらに、契約が次のようになっていると仮定します。

Groovy
/*
 * Copyright 2013-2020 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import org.springframework.cloud.contract.spec.Contract

Contract.make {
	request {
		method('PUT')
		headers {
			contentType(applicationJson())
		}
		body(file("request.json"))
		url("/1")
	}
	response {
		status OK()
		body(file("response.json"))
		headers {
			contentType(applicationJson())
		}
	}
}
YAML
request:
  method: GET
  url: /foo
  bodyFromFile: request.json
response:
  status: 200
  bodyFromFile: response.json
Java
import java.util.Collection;
import java.util.Collections;
import java.util.function.Supplier;

import org.springframework.cloud.contract.spec.Contract;

class contract_rest_from_file implements Supplier<Collection<Contract>> {

	@Override
	public Collection<Contract> get() {
		return Collections.singletonList(Contract.make(c -> {
			c.request(r -> {
				r.url("/foo");
				r.method(r.GET());
				r.body(r.file("request.json"));
			});
			c.response(r -> {
				r.status(r.OK());
				r.body(r.file("response.json"));
			});
		}));
	}

}
Kotlin
import org.springframework.cloud.contract.spec.ContractDsl.Companion.contract

contract {
	request {
		url = url("/1")
		method = PUT
		headers {
			contentType = APPLICATION_JSON
		}
		body = bodyFromFile("request.json")
	}
	response {
		status = OK
		body = bodyFromFile("response.json")
		headers {
			contentType = APPLICATION_JSON
		}
	}
}

さらに、JSON ファイルが次のとおりであると仮定します。

request.json
{
  "status": "REQUEST"
}
response.json
{
  "status": "RESPONSE"
}

テストまたはスタブの生成が行われると、request.json ファイルおよび response.json ファイルの内容がリクエストまたはレスポンスの本文に渡されます。ファイルの名前は、契約が存在するフォルダーに相対的な場所にあるファイルである必要があります。

ファイルの内容をバイナリ形式で渡す必要がある場合は、コード化された DSL の fileAsBytes メソッド、または YAML の bodyFromFileAsBytes フィールドを使用できます。

次の例は、バイナリファイルの内容を渡す方法を示しています。

Groovy
import org.springframework.cloud.contract.spec.Contract

Contract.make {
	request {
		url("/1")
		method(PUT())
		headers {
			contentType(applicationOctetStream())
		}
		body(fileAsBytes("request.pdf"))
	}
	response {
		status 200
		body(fileAsBytes("response.pdf"))
		headers {
			contentType(applicationOctetStream())
		}
	}
}
YAML
request:
  url: /1
  method: PUT
  headers:
    Content-Type: application/octet-stream
  bodyFromFileAsBytes: request.pdf
response:
  status: 200
  bodyFromFileAsBytes: response.pdf
  headers:
    Content-Type: application/octet-stream
Java
import java.util.Collection;
import java.util.Collections;
import java.util.function.Supplier;

import org.springframework.cloud.contract.spec.Contract;

class contract_rest_from_pdf implements Supplier<Collection<Contract>> {

	@Override
	public Collection<Contract> get() {
		return Collections.singletonList(Contract.make(c -> {
			c.request(r -> {
				r.url("/1");
				r.method(r.PUT());
				r.body(r.fileAsBytes("request.pdf"));
				r.headers(h -> {
					h.contentType(h.applicationOctetStream());
				});
			});
			c.response(r -> {
				r.status(r.OK());
				r.body(r.fileAsBytes("response.pdf"));
				r.headers(h -> {
					h.contentType(h.applicationOctetStream());
				});
			});
		}));
	}

}
Kotlin
import org.springframework.cloud.contract.spec.ContractDsl.Companion.contract

contract {
	request {
		url = url("/1")
		method = PUT
		headers {
			contentType = APPLICATION_OCTET_STREAM
		}
		body = bodyFromFileAsBytes("contracts/request.pdf")
	}
	response {
		status = OK
		body = bodyFromFileAsBytes("contracts/response.pdf")
		headers {
			contentType = APPLICATION_OCTET_STREAM
		}
	}
}
HTTP とメッセージングの両方でバイナリペイロードを操作する場合は、常にこのアプローチを使用する必要があります。

メタデータ

metadata を契約に追加できます。メタデータを介して、拡張機能に設定を渡すことができます。以下に、wiremock キーの使用例を示します。その値は、キーが stubMapping で、値が WireMock の StubMapping オブジェクトであるマップです。Spring Cloud Contract は、生成されたスタブマッピングの一部にカスタムコードをパッチできます。Webhook やカスタム遅延を追加したり、サードパーティの WireMock 拡張機能と統合したりするために、これを行うことができます。

java
Contract.make(c -> {
	c.metadata(MetadataUtil.map()
		.entry("wiremock", ContractVerifierUtil.map()
			.entry("stubMapping", "{ \"response\" : { \"fixedDelayMilliseconds\" : 2000 } }")));
}));
kotlin
contract {
	metadata("wiremock" to ("stubmapping" to """
{
  "response" : {
	"fixedDelayMilliseconds": 2000
  }
}"""))
}

次のセクションでは、サポートされているメタデータエントリの例を示します。

HTTP の契約

Spring Cloud Contract を使用すると、通信手段として REST または HTTP を使用するアプリケーションを検証できます。Spring Cloud Contract は、契約の request 部分の条件に一致するリクエストに対して、サーバーが契約の response 部分に準拠したレスポンスを提供することを検証します。その後、契約を使用して、指定された条件に一致するリクエストに対して適切なレスポンスを提供する WireMock スタブが生成されます。