Reprinted: https: //www.jianshu.com/p/e3277824a10a
And dummy service as
Spring Cloud Contract is a what?
Spring Cloud Contract provides support for the development of JVM-based application by CDC (Customer Driven Contracts). It provides a new way to test TDD (Test Driven Development) - based interface.
Why use the contract to do the test?
Just look at the use of micro-services architecture, there is a call follows the relationship between the various services if your area:
When you want to test a particular focus on service, other services need to have played together, they could be tested. Alternatively, write a lot of integration tests, all of the external service calls are mock out.
The cost of testing these two methods are high. So how to solve this problem?
The answer is: Compact test
-
Advantage contract testing
once defined the contract between the service and the service, Spring cloud contract will provide a mock server stub for the service consumer side, so that users can focus on their own to test the service, you also do not need to write a lot of integration tests .
-
Contract applicable test scenarios
, not all of the scenes are applicable, if the service does not rely too much external calls that did not actually write the necessary contractual tests. Only when dependent on many services, but particularly rely on the system, contract test will apply. -
Cost contract testing
strengths contract is that, after the signing of the contract between the upstream and downstream, either on the contract has been modified, the other party will be able to know. However, if you just add a unilateral contract testing, in fact, the significance is not great, at best, just to test the api documentation.
In the use of the process, when there are complex business scenario is, we often need to mock because a lot of data, but it takes a long time to prepare for the test data, to this end may need to write a lot of contracts.
How to define the contract it?
Spring Cloud Contract现在支持2种格式 yaml和groovy。
groovy灵活性比较高,但是上手成本有点高。
org.springframework.cloud.contract.spec.Contract.make {
request {
method 'PUT'
url '/api/12'
headers {
header 'Content-Type': 'application/vnd.org.springframework.cloud.contract.verifier.twitter-places-analyzer.v1+json'
}
body '''\
[{
"created_at": "Sat Jul 26 09:38:57 +0000 2014",
"id": 492967299297845248,
"id_str": "492967299297845248",
"text": "Gonna see you at Warsaw",
"place":
{
"attributes":{},
"bounding_box":
{
"coordinates":
[[
[-77.119759,38.791645],
[-76.909393,38.791645],
[-76.909393,38.995548],
[-77.119759,38.995548]
]],
"type":"Polygon"
},
"country":"United States",
"country_code":"US",
"full_name":"Washington, DC",
"id":"01fbe706f872cb32",
"name":"Washington",
"place_type":"city",
"url": "http://api.twitter.com/1/geo/id/01fbe706f872cb32.json"
}
}]
'''
}
response {
status OK()
}
}
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)
我个人还是比较倾向于使用yaml,主要还是因为yaml语法比较简单,同时,对于90%的契约,其实都是简单型契约,很少会遇到复杂的使用场景,如果你要写一个特别复杂的契约,可能你就需要好好想想如何简化这个契约了。
契约只要组成部分就是 request(method,url,body,headers),response(status,body),我们比较常用的方式是 将request的body和response的body定义成2个json文件,然后,使用fromFile方法直接引用。
groovy 写法
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(textPlain())
}
}
}
yaml写法
request:
method: GET
url: /foo
bodyFromFile: request.json
response:
status: 200
bodyFromFile: response.json
request.json
{ "status" : "REQUEST" }
response.json
{ "status" : "RESPONSE" }
附上源码:https://github.com/huleTW/spring-contract-yaml-demo/tree/master