常用頂層元素
描述
您可以為您的契約新增 description
。描述是任意文字。以下程式碼顯示範例
org.springframework.cloud.contract.spec.Contract.make {
description('''
given:
An input
when:
Sth happens
then:
Output
''')
}
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)
Contract.make(c -> {
c.description("Some description");
}));
contract {
description = """
given:
An input
when:
Sth happens
then:
Output
"""
}
名稱
您可以為您的契約提供名稱。假設您提供以下名稱:should register a user
。如果您這樣做,自動產生的測試名稱將為 validate_should_register_a_user
。此外,WireMock Stub 中的 Stub 名稱將為 should_register_a_user.json
。
您必須確保名稱不包含任何會導致產生的測試無法編譯的字元。此外,請記住,如果您為多個契約提供相同的名稱,您的自動產生測試將無法編譯,且您產生的 Stub 將互相覆寫。 |
以下範例顯示如何將名稱新增至契約
org.springframework.cloud.contract.spec.Contract.make {
name("some_special_name")
}
name: some name
Contract.make(c -> {
c.name("some name");
}));
contract {
name = "some_special_name"
}
忽略契約
如果您想要忽略契約,您可以設定外掛程式組態中忽略契約的值,或在契約本身上設定 ignored
屬性。以下範例顯示如何執行此操作
org.springframework.cloud.contract.spec.Contract.make {
ignored()
}
ignored: true
Contract.make(c -> {
c.ignored();
}));
contract {
ignored = true
}
進行中的契約
進行中的契約不會在生產者端產生測試,但允許產生 Stub。
請謹慎使用此功能,因為它可能會導致誤報,因為您產生 Stub 供消費者使用,但實際上尚未實作。 |
如果您想要設定進行中的契約,以下範例顯示如何執行此操作
org.springframework.cloud.contract.spec.Contract.make {
inProgress()
}
inProgress: true
Contract.make(c -> {
c.inProgress();
}));
contract {
inProgress = true
}
您可以設定 failOnInProgress
Spring Cloud Contract 外掛程式屬性的值,以確保當您的來源中至少有一個進行中的契約時,您的建置會中斷。
從檔案傳遞值
從版本 1.2.0
開始,您可以從檔案傳遞值。假設您的專案中有以下資源
└── src
└── test
└── resources
└── contracts
├── readFromFile.groovy
├── request.json
└── response.json
進一步假設您的契約如下
/*
* 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())
}
}
}
request:
method: GET
url: /foo
bodyFromFile: request.json
response:
status: 200
bodyFromFile: response.json
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"));
});
}));
}
}
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 檔案如下
{
"status": "REQUEST"
}
{
"status": "RESPONSE"
}
當進行測試或 Stub 產生時,request.json
和 response.json
檔案的內容會傳遞至要求或回應的主體。檔案名稱必須是相對於契約所在資料夾位置的檔案。
如果您需要以二進位格式傳遞檔案的內容,您可以使用程式碼 DSL 中的 fileAsBytes
方法或 YAML 中的 bodyFromFileAsBytes
欄位。
以下範例顯示如何傳遞二進位檔案的內容
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())
}
}
}
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
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());
});
});
}));
}
}
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
您可以將 metadata
新增至您的契約。透過 metadata,您可以將組態傳遞至擴充功能。以下您可以找到使用 wiremock
金鑰的範例。其值是一個地圖,其金鑰為 stubMapping
,值為 WireMock 的 StubMapping
物件。Spring Cloud Contract 能夠使用您的自訂程式碼修補您產生的 Stub 對應的部分。您可能想要這樣做,以便新增 Webhook、自訂延遲或與第三方 WireMock 擴充功能整合。
Contract.make {
request {
method GET()
url '/drunks'
}
response {
status OK()
body([
count: 100
])
headers {
contentType("application/json")
}
}
metadata([
wiremock: [
stubMapping: '''\
{
"response" : {
"fixedDelayMilliseconds": 2000
}
}
'''
]
])
}
name: "should count all frauds"
request:
method: GET
url: /yamlfrauds
response:
status: 200
body:
count: 200
headers:
Content-Type: application/json
metadata:
wiremock:
stubMapping: >
{
"response" : {
"fixedDelayMilliseconds": 2000
}
}
Contract.make(c -> {
c.metadata(MetadataUtil.map().entry("wiremock", ContractVerifierUtil.map().entry("stubMapping",
"{ \"response\" : { \"fixedDelayMilliseconds\" : 2000 } }")));
}));
contract {
metadata("wiremock" to ("stubmapping" to """
{
"response" : {
"fixedDelayMilliseconds": 2000
}
}"""))
}
在以下章節中,您可以找到支援的 metadata 條目的範例。