我正在使用 Spring Cloud Contract Verifier
org.springframework.cloud:spring-cloud-starter-contract-verifier:jar:2.0.0.M8 org.springframework.cloud:spring-cloud-contract-maven-plugin:1.2.4.RELEASE
我有以下契约(Contract):
request:
method: GET
url: /cars/list
response:
status: 200
headers:
Content-Type: application/json;charset=UTF-8
body:
cars:
[
{
"make": "Ford",
"model": "Fiesta",
"year": 2016,
"price": 16500.50
},
{
"make": "BMW",
"model": "X1",
"year": 2014,
"price": 22000.00
},
{
"make": "NISSAN",
"model": "Juke",
"year": 2017,
"price": 19300.00
}
]
然后在以下 java 代码中进行转换:
DocumentContext parsedJson = JsonPath.parse(response.getBody().asString());
assertThatJson(parsedJson).array("['cars']").contains("['model']").isEqualTo("Juke");
assertThatJson(parsedJson).array("['cars']").contains("['make']").isEqualTo("Ford");
assertThatJson(parsedJson).array("['cars']").contains("['year']").isEqualTo(2014);
assertThatJson(parsedJson).array("['cars']").contains("['year']").isEqualTo(2016);
assertThatJson(parsedJson).array("['cars']").contains("['model']").isEqualTo("Fiesta");
assertThatJson(parsedJson).array("['cars']").contains("['make']").isEqualTo("BMW");
assertThatJson(parsedJson).array("['cars']").contains("['year']").isEqualTo(2017);
assertThatJson(parsedJson).array("['cars']").contains("['make']").isEqualTo("NISSAN");
assertThatJson(parsedJson).array("['cars']").contains("['price']").isEqualTo(16500.5);
assertThatJson(parsedJson).array("['cars']").contains("['model']").isEqualTo("X1");
assertThatJson(parsedJson).array("['cars']").contains("['price']").isEqualTo(22000.0);
assertThatJson(parsedJson).array("['cars']").contains("['price']").isEqualTo(19300.0);
我在这个测试中遇到了一些问题:
1) 它不考虑顺序,这意味着以下正文仍将被视为有效:
{
"cars": [
{
"make": "NISSAN",
"model": "Juke",
"year": 2017,
"price": 19300.00
},
{
"make": "BMW",
"model": "X1",
"year": 2014,
"price": 22000.00
},
{
"make": "Ford",
"model": "Fiesta",
"year": 2016,
"price": 16500.50
}
]
}
2) 它只是验证某个属性是否存在于响应中的任何位置,这意味着以下正文仍将被视为有效:
{
"cars": [
{
"make": "Ford",
"model": "Juke",
"year": 2016,
"price": 19300.00
},
{
"make": "BMW",
"model": "X1",
"year": 2017,
"price": 22000.00
},
{
"make": "NISSAN",
"model": "Fiesta",
"year": 2014,
"price": 16500.50
}
]
}
3) 它忽略响应中存在的任何额外值,这意味着以下正文仍将被视为有效:
{
"cars": [
{
"make": "Ford",
"model": "Fiesta",
"year": 2017,
"price": 22000.00,
"state": "good"
},
{
"make": "NISSAN",
"model": "Juke",
"year": 2016,
"price": 19300.00,
"state": "ok"
},
{
"make": "BMW",
"model": "X1",
"year": 2014,
"price": 16500.50
},
{
"make": "Volkswagen",
"model": "Golf",
"year": 2018,
"price": 12500.00,
"state": "new"
}
]
}
我希望生成的测试更严格,并在上述情况中列出的任何差异上失败。
可以用Spring Cloud Contract Verifier实现吗?
最佳答案
首先你的版本不匹配
org.springframework.cloud:spring-cloud-starter-contract-verifier:jar:2.0.0.M8 org.springframework.cloud:spring-cloud-contract-maven-plugin:1.2.4.RELEASE
您使用的插件版本与验证程序不同。那些应该匹配。
现在回答你的问题
1) It does not take order into account, meaning the following body would still be considered valid:
是的,我们不会开箱即用地对其进行测试。您可以通过为整个正文 ( https://cloud.spring.io/spring-cloud-contract/single/spring-cloud-contract.html#contract-matchers ) 提供自己的 JSON 路径匹配器来手动完成此操作
2) It just verifies that certain property is present anywhere in the response, meaning the following body would still be considered valid:
是的,我们断言结构没问题,这就是合约测试的思路。如果您想要更精确的验证,请使用匹配器部分 ( https://cloud.spring.io/spring-cloud-contract/single/spring-cloud-contract.html#contract-matchers )
3) It ignores any extra values present in the response, meaning the following body would still be considered valid:
这绝对是您应该做的。忽略未知字段。您可以在此处阅读有关 Postel 定律的更多信息 (https://en.wikipedia.org/wiki/Robustness_principle)
I would like the generated test to be more strict and fail on any differences outlined in cases above.
我认为您正在寻找一个模式而不是契约(Contract)测试或定义。您可以使用 Spring Rest Docs 集成 ( https://cloud.spring.io/spring-cloud-contract/single/spring-cloud-contract.html#_generating_stubs_using_rest_docs ) 并在那里强制执行 stub 的外观。但是 IMO(当然我不知道你的域)你太严格了。
关于spring-boot - Spring Cloud Contract Verifier - body 匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49874812/