creating and testing rest contracts with accurest gradle
TRANSCRIPT
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
1 z 112 13.06.2016 13:47
/ [email protected]@olga_maciaszek
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
2 z 112 13.06.2016 13:47
1. Introduction
2. Background
3. Solution
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
3 z 112 13.06.2016 13:47
Accurest - Consumer Driven ContractsAccurest - Consumer Driven Contracts
Verifier for REST and MessagingVerifier for REST and Messaging
Easy to write scripts
Works out of the box with Gradle and Maven
Automatically generated WireMock and Messaging stubs
Automatically generated Spock/ JUnit tests
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
4 z 112 13.06.2016 13:47
Tech StackTech Stack
Gradle, Maven
Java, Groovy
REST: Standalone App, MockMvc, JAX-RS
Messaging: Spring Integration, Spring Cloud Stream,
Apache Camel
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
5 z 112 13.06.2016 13:47
MonolithMonolith
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
6 z 112 13.06.2016 13:47
Lengthy and Costly Development Process
Long Testing Times
Long Deployment Times
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
7 z 112 13.06.2016 13:47
MicroservicesMicroservices
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
8 z 112 13.06.2016 13:47
Many smaller services
Each team responsible for its service
REST communication
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
9 z 112 13.06.2016 13:47
New Issues and ChallengesNew Issues and Challenges
Creating and modifying REST contracts
Testing a Microservice-based system
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
10 z 112 13.06.2016 13:47
New Issues and ChallengesNew Issues and Challenges
Creating and modifying REST contracts
Testing a Microservice-based system
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
11 z 112 13.06.2016 13:47
One server + limited clients
vs.
Multiple client/servers communicating with each other
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
12 z 112 13.06.2016 13:47
Defining and modifying REST contracts much more often
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
13 z 112 13.06.2016 13:47
Quick information when the REST contract is modified
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
14 z 112 13.06.2016 13:47
Various clients requesting different changes at the same
time
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
15 z 112 13.06.2016 13:47
RequirementsRequirements
Consumer Driven Contracts
All consumers need to be notified when the Contract has
changed
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
16 z 112 13.06.2016 13:47
New Issues and ChallengesNew Issues and Challenges
Creating and modifying REST contracts
Testing a Microservice-based system
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
17 z 112 13.06.2016 13:47
Monolith E2E TestsMonolith E2E Tests
Comprehensive
Verified borders
Considerably improved safety
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
18 z 112 13.06.2016 13:47
1 to rule them all1 to rule them all
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
19 z 112 13.06.2016 13:47
Against the very idea of microservices!Against the very idea of microservices!
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
20 z 112 13.06.2016 13:47
1 pipeline per service, all the1 pipeline per service, all the
collaborators addedcollaborators added
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
21 z 112 13.06.2016 13:47
Too costly!Too costly!
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
22 z 112 13.06.2016 13:47
Stubbed collaboratorsStubbed collaborators
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
23 z 112 13.06.2016 13:47
Stubs get corrodedStubs get corroded
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
24 z 112 13.06.2016 13:47
RequirementsRequirements
Stubs required
Validating stubs against servers required
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
25 z 112 13.06.2016 13:47
RequirementsRequirements
Consumer Driven Contracts
All consumers need to be notified when the Contract has
changed
Stubs required
Validating stubs against servers required
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
26 z 112 13.06.2016 13:47
AccurestAccurest
Scripts that define the REST contracts are submitted as PRs
by the client teams
Scripts are used to generate both WireMock stubs and
server tests
New server version along the new stubs only published
when server tests have passed
Client services download server stubs and use them for
tests
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
27 z 112 13.06.2016 13:47
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
28 z 112 13.06.2016 13:47
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
29 z 112 13.06.2016 13:47
io.codearte.accurest.dsl.Accurest.make request { method 'PUT' url '/fraudcheck' body( clientId: "12345678902", loanAmount: 99999 ) headers { header('Content-Type', 'application/vnd.fraud.v1+json') } } response { status 200 body( fraudCheckStatus: "FRAUD", rejectionReason: "Amount too high" ) headers { header('Content-Type': 'application/vnd.fraud.v1+json') } } }
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
30 z 112 13.06.2016 13:47
io.codearte.accurest.dsl.Accurest.make request { method 'PUT' url '/fraudcheck' body( clientId: "12345678902", loanAmount: 99999 ) headers { header('Content-Type', 'application/vnd.fraud.v1+json') } } response { status 200 body( fraudCheckStatus: "FRAUD", rejectionReason: "Amount too high" ) headers { header('Content-Type': 'application/vnd.fraud.v1+json') } } }
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
31 z 112 13.06.2016 13:47
io.codearte.accurest.dsl.Accurest.make request { method 'PUT' url '/fraudcheck' body( clientId: "12345678902", loanAmount: 99999 ) headers { header('Content-Type', 'application/vnd.fraud.v1+json') } } response { status 200 body( fraudCheckStatus: "FRAUD", rejectionReason: "Amount too high" ) headers { header('Content-Type': 'application/vnd.fraud.v1+json') } } }
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
32 z 112 13.06.2016 13:47
io.codearte.accurest.dsl.Accurest.make request { method 'PUT' url '/fraudcheck' body( clientId: "12345678902", loanAmount: 99999 ) headers { header('Content-Type', 'application/vnd.fraud.v1+json') } } response { status 200 body( fraudCheckStatus: "FRAUD", rejectionReason: "Amount too high" ) headers { header('Content-Type': 'application/vnd.fraud.v1+json') } } }
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
33 z 112 13.06.2016 13:47
io.codearte.accurest.dsl.Accurest.make request { method 'PUT' url '/fraudcheck' body( clientId: "12345678902", loanAmount: 99999 ) headers { header('Content-Type', 'application/vnd.fraud.v1+json') } } response { status 200 body( fraudCheckStatus: "FRAUD", rejectionReason: "Amount too high" ) headers { header('Content-Type': 'application/vnd.fraud.v1+json') } } }
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
34 z 112 13.06.2016 13:47
io.codearte.accurest.dsl.Accurest.make request { method 'PUT' url '/fraudcheck' body( clientId: "12345678902", loanAmount: 99999 ) headers { header('Content-Type', 'application/vnd.fraud.v1+json') } } response { status 200 body( fraudCheckStatus: "FRAUD", rejectionReason: "Amount too high" ) headers { header('Content-Type': 'application/vnd.fraud.v1+json') } } }
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
35 z 112 13.06.2016 13:47
io.codearte.accurest.dsl.Accurest.make request { method 'PUT' url '/fraudcheck' body( clientId: "12345678902", loanAmount: 99999 ) headers { header('Content-Type', 'application/vnd.fraud.v1+json') } } response { status 200 body( fraudCheckStatus: "FRAUD", rejectionReason: "Amount too high" ) headers { header('Content-Type': 'application/vnd.fraud.v1+json') } } }
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
36 z 112 13.06.2016 13:47
io.codearte.accurest.dsl.Accurest.make request { method 'PUT' url '/fraudcheck' body( clientId: "12345678902", loanAmount: 99999 ) headers { header('Content-Type', 'application/vnd.fraud.v1+json') } } response { status 200 body( fraudCheckStatus: "FRAUD", rejectionReason: "Amount too high" ) headers { header('Content-Type': 'application/vnd.fraud.v1+json') } } }
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
37 z 112 13.06.2016 13:47
io.codearte.accurest.dsl.Accurest.make request { method 'PUT' url '/fraudcheck' body( clientId: "12345678902", loanAmount: 99999 ) headers { header('Content-Type', 'application/vnd.fraud.v1+json') } } response { status 200 body( fraudCheckStatus: "FRAUD", rejectionReason: "Amount too high" ) headers { header('Content-Type': 'application/vnd.fraud.v1+json') } } }
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
38 z 112 13.06.2016 13:47
io.codearte.accurest.dsl.Accurest.make request { method 'PUT' url '/fraudcheck' body( clientId: "12345678902", loanAmount: 99999 ) headers { header('Content-Type', 'application/vnd.fraud.v1+json') } } response { status 200 body( fraudCheckStatus: "FRAUD", rejectionReason: "Amount too high" ) headers { header('Content-Type': 'application/vnd.fraud.v1+json') } } }
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
39 z 112 13.06.2016 13:47
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
40 z 112 13.06.2016 13:47
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
41 z 112 13.06.2016 13:47
WireMockWireMock
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
42 z 112 13.06.2016 13:47
{ "request" : { "url" : "/fraudcheck", "method" : "PUT", "bodyPatterns" : [ { "matchesJsonPath" : "$[?(@.loanAmount == 99999)]" }, { "matchesJsonPath" : "$[?(@.clientId == '12345678902')]" } ], "headers" : { "Content-Type" : { "equalTo" : "application/vnd.fraud.v1+json" } } }, "response" : { "status" : 200, "body" : "{\"fraudCheckStatus\":\"FRAUD\", \"rejectionReason\":\"Amount too high\"}", "headers" : { "Content-Type" : "application/vnd.fraud.v1+json" } }}
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
43 z 112 13.06.2016 13:47
{ "request" : { "url" : "/fraudcheck", "method" : "PUT", "bodyPatterns" : [ { "matchesJsonPath" : "$[?(@.loanAmount == 99999)]" }, { "matchesJsonPath" : "$[?(@.clientId == '12345678902')]" } ], "headers" : { "Content-Type" : { "equalTo" : "application/vnd.fraud.v1+json" } } } , "response" : { "status" : 200, "body" : "{\"fraudCheckStatus\":\"FRAUD\", \"rejectionReason\":\"Amount too high\"}", "headers" : { "Content-Type" : "application/vnd.fraud.v1+json" } }}
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
44 z 112 13.06.2016 13:47
io.codearte.accurest.dsl.Accurest.make request { method 'PUT' url '/fraudcheck' body( clientId: "12345678902", loanAmount: 99999 ) headers { header('Content-Type', 'application/vnd.fraud.v1+json') } } response { status 200 body( fraudCheckStatus: "FRAUD", rejectionReason: "Amount too high" ) headers { header('Content-Type': 'application/vnd.fraud.v1+json') } } }
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
45 z 112 13.06.2016 13:47
{"request" : { "url" : "/fraudcheck", "method" : "PUT", "bodyPatterns" : [ { "matchesJsonPath" : "$[?(@.loanAmount == 99999)]" }, { "matchesJsonPath" : "$[?(@.clientId == '12345678902')]" } ], "headers" : { "Content-Type" : { "equalTo" : "application/vnd.fraud.v1+json" } } }, "response" : { "status" : 200, "body" : "{\"fraudCheckStatus\":\"FRAUD\", \"rejectionReason\":\"Amount too high\"}", "headers" : { "Content-Type" : "application/vnd.fraud.v1+json" } }}
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
46 z 112 13.06.2016 13:47
io.codearte.accurest.dsl.Accurest.make request { method 'PUT' url '/fraudcheck' body( clientId: "12345678902", loanAmount: 99999 ) headers { header('Content-Type', 'application/vnd.fraud.v1+json') } } response { status 200 body( fraudCheckStatus: "FRAUD", rejectionReason: "Amount too high" ) headers { header('Content-Type': 'application/vnd.fraud.v1+json') } } }
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
47 z 112 13.06.2016 13:47
{"request" : { "url" : "/fraudcheck", "method" : "PUT", "bodyPatterns" : [ { "matchesJsonPath" : "$[?(@.loanAmount == 99999)]" }, { "matchesJsonPath" : "$[?(@.clientId == '12345678902')]" } ], "headers" : { "Content-Type" : { "equalTo" : "application/vnd.fraud.v1+json" } } }, "response" : { "status" : 200, "body" : "{\"fraudCheckStatus\":\"FRAUD\", \"rejectionReason\":\"Amount too high\"}", "headers" : { "Content-Type" : "application/vnd.fraud.v1+json" } }}
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
48 z 112 13.06.2016 13:47
io.codearte.accurest.dsl.Accurest.make request { method 'PUT' url '/fraudcheck' body( clientId: "12345678902", loanAmount: 99999 ) headers { header('Content-Type', 'application/vnd.fraud.v1+json') } } response { status 200 body( fraudCheckStatus: "FRAUD", rejectionReason: "Amount too high" ) headers { header('Content-Type': 'application/vnd.fraud.v1+json') } } }
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
49 z 112 13.06.2016 13:47
{"request" : { "url" : "/fraudcheck", "method" : "PUT", "bodyPatterns" : [ { "matchesJsonPath" : "$[?(@.loanAmount == 99999)]" }, { "matchesJsonPath" : "$[?(@.clientId == '12345678902')]" } ], "headers" : { "Content-Type" : { "equalTo" : "application/vnd.fraud.v1+json" } } }, "response" : { "status" : 200, "body" : "{\"fraudCheckStatus\":\"FRAUD\", \"rejectionReason\":\"Amount too high\"}", "headers" : { "Content-Type" : "application/vnd.fraud.v1+json" } }}
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
50 z 112 13.06.2016 13:47
io.codearte.accurest.dsl.Accurest.make request { method 'PUT' url '/fraudcheck' body( clientId: "12345678902", loanAmount: 99999 ) headers { header('Content-Type', 'application/vnd.fraud.v1+json') } } response { status 200 body( fraudCheckStatus: "FRAUD", rejectionReason: "Amount too high" ) headers { header('Content-Type': 'application/vnd.fraud.v1+json') } } }
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
51 z 112 13.06.2016 13:47
{"request" : { "url" : "/fraudcheck", "method" : "PUT", "bodyPatterns" : [ { "matchesJsonPath" : "$[?(@.loanAmount == 99999)]" }, { "matchesJsonPath" : "$[?(@.clientId == '12345678902')]" } ], "headers" : { "Content-Type" : { "equalTo" : "application/vnd.fraud.v1+json" } } }, "response" : { "status" : 200, "body" : "{\"fraudCheckStatus\":\"FRAUD\", \"rejectionReason\":\"Amount too high\"}", "headers" : { "Content-Type" : "application/vnd.fraud.v1+json" } }}
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
52 z 112 13.06.2016 13:47
{"request" : { "url" : "/fraudcheck", "method" : "PUT", "bodyPatterns" : [ { "matchesJsonPath" : "$[?(@.loanAmount == 99999)]" }, { "matchesJsonPath" : "$[?(@.clientId == '12345678902')]" } ], "headers" : { "Content-Type" : { "equalTo" : "application/vnd.fraud.v1+json" } } }, "response" : { "status" : 200, "body" : "{\"fraudCheckStatus\":\"FRAUD\", \"rejectionReason\":\"Amount too high\"}", "headers" : { "Content-Type" : "application/vnd.fraud.v1+json" } }}
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
53 z 112 13.06.2016 13:47
io.codearte.accurest.dsl.Accurest.make request { method 'PUT' url '/fraudcheck' body( clientId: "12345678902", loanAmount: 99999 ) headers { header('Content-Type', 'application/vnd.fraud.v1+json') } } response { status 200 body( fraudCheckStatus: "FRAUD", rejectionReason: "Amount too high" ) headers { header('Content-Type': 'application/vnd.fraud.v1+json') } } }
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
54 z 112 13.06.2016 13:47
{"request" : { "url" : "/fraudcheck", "method" : "PUT", "bodyPatterns" : [ { "matchesJsonPath" : "$[?(@.loanAmount == 99999)]" }, { "matchesJsonPath" : "$[?(@.clientId == '12345678902')]" } ], "headers" : { "Content-Type" : { "equalTo" : "application/vnd.fraud.v1+json" } } }, "response" : { "status" : 200, "body" : "{\"fraudCheckStatus\":\"FRAUD\", \"rejectionReason\":\"Amount too high\"}", "headers" : { "Content-Type" : "application/vnd.fraud.v1+json" } }}
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
55 z 112 13.06.2016 13:47
io.codearte.accurest.dsl.Accurest.make request { method 'PUT' url '/fraudcheck' body( clientId: "12345678902", loanAmount: 99999 ) headers { header('Content-Type', 'application/vnd.fraud.v1+json') } } response { status 200 body( fraudCheckStatus: "FRAUD", rejectionReason: "Amount too high" ) headers { header('Content-Type': 'application/vnd.fraud.v1+json') } } }
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
56 z 112 13.06.2016 13:47
{"request" : { "url" : "/fraudcheck", "method" : "PUT", "bodyPatterns" : [ { "matchesJsonPath" : "$[?(@.loanAmount == 99999)]" }, { "matchesJsonPath" : "$[?(@.clientId == '12345678902')]" } ], "headers" : { "Content-Type" : { "equalTo" : "application/vnd.fraud.v1+json" } } }, "response" : { "status" : 200, "body" : "{\"fraudCheckStatus\":\"FRAUD\", \"rejectionReason\":\"Amount too high\"}", "headers" : { "Content-Type" : "application/vnd.fraud.v1+json" } }}
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
57 z 112 13.06.2016 13:47
io.codearte.accurest.dsl.Accurest.make request { method 'PUT' url '/fraudcheck' body( clientId: "12345678902", loanAmount: 99999 ) headers { header('Content-Type', 'application/vnd.fraud.v1+json') } } response { status 200 body( fraudCheckStatus: "FRAUD", rejectionReason: "Amount too high" ) headers { header('Content-Type': 'application/vnd.fraud.v1+json') } } }
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
58 z 112 13.06.2016 13:47
{"request" : { "url" : "/fraudcheck", "method" : "PUT", "bodyPatterns" : [ { "matchesJsonPath" : "$[?(@.loanAmount == 99999)]" }, { "matchesJsonPath" : "$[?(@.clientId == '12345678902')]" } ], "headers" : { "Content-Type" : { "equalTo" : "application/vnd.fraud.v1+json" } } }, "response" : { "status" : 200, "body" : "{\"fraudCheckStatus\":\"FRAUD\", \"rejectionReason\":\"Amount too high\"}", "headers" : { "Content-Type" : "application/vnd.fraud.v1+json" } }}
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
59 z 112 13.06.2016 13:47
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
60 z 112 13.06.2016 13:47
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
61 z 112 13.06.2016 13:47
def validate_shouldMarkClientAsFraud() { given:
def request = given().header('Content-Type', 'application/vnd.fraud.v1+json').body('{"clientId":"12345678902","loanAmount":99999}')
when:def response = given().spec(request).put("/fraudcheck")
then: response.statusCode == 200 response.header('Content-Type') == 'application/vnd.fraud.v1+json' and:
DocumentContext parsedJson = JsonPath.parse(response.body.asString())assertTassertThatJson(parsedJson).field("rejectionReason")
.isEqualTo("Amount too high") assertThatJson(parsedJson).field("fraudCheckStatus").isEqualTo("FRAUD")
}
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
62 z 112 13.06.2016 13:47
com.jayway.RestAssured
com.toomuchcoding.jsonassert
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
63 z 112 13.06.2016 13:47
io.codearte.accurest.dsl.Accurest.make request { method 'PUT' url '/fraudcheck' body( clientId: "12345678902", loanAmount: 99999 ) headers { header('Content-Type', 'application/vnd.fraud.v1+json') } } response { status 200 body( fraudCheckStatus: "FRAUD", rejectionReason: "Amount too high" ) headers { header('Content-Type': 'application/vnd.fraud.v1+json') } } }
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
64 z 112 13.06.2016 13:47
def validate_shouldMarkClientAsFraud() { given:
def request = given().header('Content-Type', 'application/vnd.fraud.v1+json').body('{"clientId":"12345678902","loanAmount":99999}')
when:def response = given().spec(request).put("/fraudcheck")
then: response.statusCode == 200 response.header('Content-Type') == 'application/vnd.fraud.v1+json' and:
DocumentContext parsedJson = JsonPath.parse(response.body.asString())assertTassertThatJson(parsedJson).field("rejectionReason")
.isEqualTo("Amount too high") assertThatJson(parsedJson).field("fraudCheckStatus").isEqualTo("FRAUD")
}
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
65 z 112 13.06.2016 13:47
io.codearte.accurest.dsl.Accurest.make request { method 'PUT' url '/fraudcheck' body( clientId: "12345678902", loanAmount: 99999 ) headers { header('Content-Type', 'application/vnd.fraud.v1+json') } } response { status 200 body( fraudCheckStatus: "FRAUD", rejectionReason: "Amount too high" ) headers { header('Content-Type': 'application/vnd.fraud.v1+json') } } }
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
66 z 112 13.06.2016 13:47
def validate_shouldMarkClientAsFraud() { given:
def request = given().header('Content-Type', 'application/vnd.fraud.v1+json').body('{"clientId":"12345678902","loanAmount":99999}')
when:def response = given().spec(request).put("/fraudcheck")
then:response.statusCode == 200
response.header('Content-Type') == 'application/vnd.fraud.v1+json' and:
DocumentContext parsedJson = JsonPath.parse(response.body.asString())assertThatJson(parsedJson).field("rejectionReason")
.isEqualTo("Amount too high") assertThatJson(parsedJson).field("fraudCheckStatus").isEqualTo("FRAUD")
}
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
67 z 112 13.06.2016 13:47
io.codearte.accurest.dsl.Accurest.make request { method 'PUT' url '/fraudcheck' body( clientId: "12345678902", loanAmount: 99999 ) headers { header('Content-Type', 'application/vnd.fraud.v1+json') } } response { status 200 body( fraudCheckStatus: "FRAUD", rejectionReason: "Amount too high" ) headers { header('Content-Type': 'application/vnd.fraud.v1+json') } } }
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
68 z 112 13.06.2016 13:47
def validate_shouldMarkClientAsFraud() { given:
def request = given().header('Content-Type', 'application/vnd.fraud.v1+json').body('{"clientId":"12345678902","loanAmount":99999}')
when:def response = given().spec(request).put("/fraudcheck")
then:response.statusCode == 200
response.header('Content-Type') == 'application/vnd.fraud.v1+json' and:
DocumentContext parsedJson = JsonPath.parse(response.body.asString())assertThatJson(parsedJson).field("rejectionReason")
.isEqualTo("Amount too high") assertThatJson(parsedJson).field("fraudCheckStatus").isEqualTo("FRAUD")
}
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
69 z 112 13.06.2016 13:47
io.codearte.accurest.dsl.Accurest.make request { method 'PUT' url '/fraudcheck' body( clientId: "12345678902", loanAmount: 99999 ) headers { header('Content-Type', 'application/vnd.fraud.v1+json') } } response { status 200 body( fraudCheckStatus: "FRAUD", rejectionReason: "Amount too high" ) headers { header('Content-Type': 'application/vnd.fraud.v1+json') } } }
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
70 z 112 13.06.2016 13:47
def validate_shouldMarkClientAsFraud() { given:
def request = given().header('Content-Type', 'application/vnd.fraud.v1+json').body('{"clientId":"12345678902","loanAmount":99999}')
when:def response = given().spec(request).put("/fraudcheck")
then:response.statusCode == 200
response.header('Content-Type') == 'application/vnd.fraud.v1+json' and:
DocumentContext parsedJson = JsonPath.parse(response.body.asString())assertThatJson(parsedJson).field("rejectionReason")
.isEqualTo("Amount too high") assertThatJson(parsedJson).field("fraudCheckStatus").isEqualTo("FRAUD")
}
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
71 z 112 13.06.2016 13:47
io.codearte.accurest.dsl.Accurest.make request { method 'PUT' url '/fraudcheck' body( clientId: "12345678902", loanAmount: 99999 ) headers { header('Content-Type', 'application/vnd.fraud.v1+json') } } response { status 200 body( fraudCheckStatus: "FRAUD", rejectionReason: "Amount too high" ) headers { header('Content-Type': 'application/vnd.fraud.v1+json') } } }
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
72 z 112 13.06.2016 13:47
def validate_shouldMarkClientAsFraud() { given:
def request = given().header('Content-Type', 'application/vnd.fraud.v1+json').body('{"clientId":"12345678902","loanAmount":99999}')
when:def response = given().spec(request).put("/fraudcheck")
then:response.statusCode == 200
response.header('Content-Type') == 'application/vnd.fraud.v1+json' and:
DocumentContext parsedJson = JsonPath.parse(response.body.asString())assertThatJson(parsedJson).field("rejectionReason")
.isEqualTo("Amount too high") assertThatJson(parsedJson).field("fraudCheckStatus").isEqualTo("FRAUD")
}
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
73 z 112 13.06.2016 13:47
Base Test ClassBase Test Class
class BaseMockMvcSpec extends Specification {
def setup() { RestAssuredMockMvc.standaloneSetup(new PairIdController()) } }
@ContextConfiguration(classes = [PaymentResourceStubContext, ClientResourceStubContext], loader = SpringApplicationContextLoader)@WebIntegrationTestclass BaseAccurestSpec extends Specification {
@Autowired ApplicationContext context
}
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
74 z 112 13.06.2016 13:47
Regular Expression SupportRegular Expression Support
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
75 z 112 13.06.2016 13:47
io.codearte.accurest.dsl.Accurest.make request { method 'PUT' url '/fraudcheck' body( clientId: value(stub(regex('[0-9]{11}')), test("12345678902")), loanAmount: 99999 ) headers { header('Content-Type', 'application/vnd.fraud.v1+json') } } response { status 200 body( fraudCheckStatus: "FRAUD", rejectionReason: "Amount too high" ) headers { header('Content-Type': 'application/vnd.fraud.v1+json') } } }
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
76 z 112 13.06.2016 13:47
{"request" : { "url" : "/fraudcheck", "method" : "PUT", "bodyPatterns" : [ { "matchesJsonPath" : "$[?(@.loanAmount == 99999)]" }, { "matchesJsonPath" : "$[?(@.clientId =~ /[0-9]{11}/)]" } ], "headers" : { "Content-Type" : { "equalTo" : "application/vnd.fraud.v1+json" } } }, "response" : { "status" : 200, "body" : "{\"fraudCheckStatus\":\"FRAUD\", \"rejectionReason\":\"Amount too high\"}", "headers" : { "Content-Type" : "application/vnd.fraud.v1+json" } }}
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
77 z 112 13.06.2016 13:47
def validate_shouldMarkClientAsFraud() { given:
def request = given().header('Content-Type', 'application/vnd.fraud.v1+json').body('{"clientId":"12345678902" ,"loanAmount":99999}')
when:def response = given().spec(request).put("/fraudcheck")
then:response.statusCode == 200
response.header('Content-Type') == 'application/vnd.fraud.v1+json' and:
DocumentContext parsedJson = JsonPath.parse(response.body.asString())assertThatJson(parsedJson).field("rejectionReason")
.isEqualTo("Amount too high") assertThatJson(parsedJson).field("fraudCheckStatus").isEqualTo("FRAUD")
}
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
78 z 112 13.06.2016 13:47
Executing Custom Methods on theExecuting Custom Methods on the
ServerServer
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
79 z 112 13.06.2016 13:47
io.codearte.accurest.dsl.Accurest.make request { method 'PUT' url '/fraudcheck' body( clientId: "12345678902", loanAmount: 99999 ) headers { header('Content-Type', 'application/vnd.fraud.v1+json') } } response { status 200 body(fraudCheckStatus: "FRAUD",
rejectionReason: value(stub("Amount too high"), test(execute('isCorrectRejectionReason($it)')))) headers { header('Content-Type': 'application/vnd.fraud.v1+json') } } }
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
80 z 112 13.06.2016 13:47
abstract class BaseMockMvcSpec extends Specification {
def setup() { RestAssuredMockMvc.standaloneSetup(new FraudDetectionController()) }
void isCorrectRejectionReason(String rejectionReason) {assert rejectionReason == 'Amount too high'
}}
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
81 z 112 13.06.2016 13:47
def validate_shouldMarkClientAsFraud() { given:
def request = given().header('Content-Type', 'application/vnd.fraud.v1+json').body('{"clientId":"12345678902","loanAmount":99999}')
when:def response = given().spec(request).put("/fraudcheck")
then:response.statusCode == 200
response.header('Content-Type') == 'application/vnd.fraud.v1+json' and:
DocumentContext parsedJson = JsonPath.parse(response.body.asString()) assertThatJson(parsedJson).field("fraudCheckStatus").isEqualTo("FRAUD") isCorrectRejectionReason(parsedJson.read('$.rejectionReason'))
}
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
82 z 112 13.06.2016 13:47
DSL - Other Available FunctionalitiesDSL - Other Available Functionalities
Query Parameters
Optional Fields
Nested Elements
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
83 z 112 13.06.2016 13:47
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
84 z 112 13.06.2016 13:47
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
85 z 112 13.06.2016 13:47
Stubs published as jars to theStubs published as jars to the
repositoryrepository
Jar, archive
Maven Publish Plugin
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
86 z 112 13.06.2016 13:47
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
87 z 112 13.06.2016 13:47
StubRunnerStubRunner
Automated stubs download from the repository
Automated launching of WireMock server instances and
mounting the stubs
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
88 z 112 13.06.2016 13:47
StubRunner DependenciesStubRunner Dependencies
dependencies { testCompile 'io.codearte.accurest:stub-runner:1.1.0-M7' testCompile 'io.codearte.accurest:stub-runner-junit:1.1.0-M7' testCompile 'io.codearte.accurest:stub-runner-spring:1.1.0-M7' testCompile 'io.codearte.accurest:stub-runner-spring-cloud:1.1.0-M7' }
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
89 z 112 13.06.2016 13:47
Accurest JUnit RuleAccurest JUnit Rule
@ClassRule @Shared AccurestRule accurestRule = new AccurestRule().repoRoot('http://www.myrepo.com') .minPort(11000).maxPort(12000) [ || .withPort(8090)] .downloadStub('com.toomuchcoding:fraudDetectionService')
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
90 z 112 13.06.2016 13:47
Out of the box support for Spring andOut of the box support for Spring and
SpringCloudSpringCloud
StubRunnerConfiguration
@Autowired StubFinder
StubRunnerDiscoveryClient
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
91 z 112 13.06.2016 13:47
MessagingMessaging
Automated testing of messages created by the producer
Producer's messages automatically provided for consumer
tests by StubRunner
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
92 z 112 13.06.2016 13:47
Producer SideProducer Side
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
93 z 112 13.06.2016 13:47
io.codearte.accurest.dsl.Accurest.make { description 'Some Description' label 'some_label' input {
messageFrom('input') messageBody([
bookName: 'foo' ])
messageHeaders { header('sample', 'header')
} } outputMessage {
sentTo('output') body([
bookName: 'foo' ]) headers {
header('BOOK-NAME', 'foo')}
}}
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
94 z 112 13.06.2016 13:47
def validate_shouldMakeMessageTest() throws Exception {given:
def inputMessage = accurestMessaging.create('''{"bookName":"foo"}''' ,[ 'sample': 'header' ])
when: accurestMessaging.send(inputMessage, 'input')then:
def response = accurestMessaging.receiveMessage('output')assert response != nullresponse.getHeader('BOOK-NAME') == 'foo'
and:DocumentContext parsedJson = JsonPath.parse(accurestObjectMapper
.writeValueAsString(response.payload))assertThatJson(parsedJson).field("bookName").isEqualTo("foo")
}
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
95 z 112 13.06.2016 13:47
io.codearte.accurest.dsl.Accurest.make { description 'Some Description' label 'some_label' input {
messageFrom('input') messageBody([
bookName: 'foo' ])
messageHeaders { header('sample', 'header')
} } outputMessage {
sentTo('output') body([
bookName: 'foo ]) headers {
header('BOOK-NAME', 'foo')}
}}
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
96 z 112 13.06.2016 13:47
def validate_shouldMakeMessageTest() throws Exception {given:
def inputMessage = accurestMessaging.create('''{"bookName":"foo"}''' ,[ 'sample': 'header' ])
when: accurestMessaging.send(inputMessage, 'input')then:
def response = accurestMessaging.receiveMessage('output')assert response != nullresponse.getHeader('BOOK-NAME') == 'foo'
and:DocumentContext parsedJson = JsonPath.parse(accurestObjectMapper
.writeValueAsString(response.payload))assertThatJson(parsedJson).field("bookName").isEqualTo("foo")
}
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
97 z 112 13.06.2016 13:47
io.codearte.accurest.dsl.Accurest.make { description 'Some Description' label 'some_label' input {
messageFrom('input') messageBody([
bookName: 'foo' ])
messageHeaders { header('sample', 'header')
} } outputMessage {
sentTo('output') body([
bookName: 'foo ]) headers {
header('BOOK-NAME', 'foo')}
}}
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
98 z 112 13.06.2016 13:47
def validate_shouldMakeMessageTest() throws Exception {given:
def inputMessage = accurestMessaging.create('''{"bookName":"foo"}''' ,[ 'sample': 'header' ])
when: accurestMessaging.send(inputMessage, 'input')then:
def response = accurestMessaging.receiveMessage('output')assert response != nullresponse.getHeader('BOOK-NAME') == 'foo'
and:DocumentContext parsedJson = JsonPath.parse(accurestObjectMapper
.writeValueAsString(response.payload))assertThatJson(parsedJson).field("bookName").isEqualTo("foo")
}
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
99 z 112 13.06.2016 13:47
io.codearte.accurest.dsl.Accurest.make { description 'Some Description' label 'some_label' input {
messageFrom('input') messageBody([
bookName: 'foo' ])
messageHeaders { header('sample', 'header')
} } outputMessage {
sentTo('output') body([
bookName: 'foo ]) headers {
header('BOOK-NAME', 'foo')}
}}
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
100 z 112 13.06.2016 13:47
def validate_shouldMakeMessageTest() throws Exception {given:
def inputMessage = accurestMessaging.create('''{"bookName":"foo"}''' ,[ 'sample': 'header' ])
when: accurestMessaging.send(inputMessage, 'input')then:
def response = accurestMessaging.receiveMessage('output')assert response != nullresponse.getHeader('BOOK-NAME') == 'foo'
and:DocumentContext parsedJson = JsonPath.parse(accurestObjectMapper
.writeValueAsString(response.payload))assertThatJson(parsedJson).field("bookName").isEqualTo("foo")
}
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
101 z 112 13.06.2016 13:47
io.codearte.accurest.dsl.Accurest.make { description 'Some Description' label 'some_label' input {
messageFrom('input') messageBody([
bookName: 'foo' ])
messageHeaders { header('sample', 'header')
} } outputMessage {
sentTo('output') body([
bookName: 'foo ]) headers {
header('BOOK-NAME', 'foo')}
}}
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
102 z 112 13.06.2016 13:47
def validate_shouldMakeMessageTest() throws Exception {given:
def inputMessage = accurestMessaging.create('''{"bookName":"foo"}'''> ,[ 'sample': 'header' ])
when: accurestMessaging.send(inputMessage,'input')then:
def response = accurestMessaging.receiveMessage('output')assert response != nullresponse.getHeader('BOOK-NAME') == 'foo'
and:DocumentContext parsedJson = JsonPath.parse(accurestObjectMapper
.writeValueAsString(response.payload))assertThatJson(parsedJson).field("bookName").isEqualTo("foo")
}
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
103 z 112 13.06.2016 13:47
io.codearte.accurest.dsl.Accurest.make { description 'Some Description' label 'some_label' input {
messageFrom('input') messageBody([
bookName: 'foo' ])
messageHeaders { header('sample', 'header')
} } outputMessage {
sentTo('output') body([
bookName: 'foo ]) headers {
header('BOOK-NAME', 'foo')}
}}
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
104 z 112 13.06.2016 13:47
def validate_shouldMakeMessageTest() throws Exception {given:
def inputMessage = accurestMessaging.create('''{"bookName":"foo"}'''> ,[ 'sample': 'header' ])
when: accurestMessaging.send(inputMessage,'input')then:
def response = accurestMessaging.receiveMessage('output')assert response != nullresponse.getHeader('BOOK-NAME') == 'foo'
and:DocumentContext parsedJson = JsonPath.parse(accurestObjectMapper
.writeValueAsString(response.payload))assertThatJson(parsedJson).field("bookName").isEqualTo("foo")
}
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
105 z 112 13.06.2016 13:47
io.codearte.accurest.dsl.Accurest.make { description 'Some Description' label 'some_label' input {
messageFrom('input') messageBody([
bookName: 'foo' ])
messageHeaders { header('sample', 'header')
} } outputMessage {
sentTo('output') body([
bookName: 'foo ]) headers {
header('BOOK-NAME', 'foo')}
}}
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
106 z 112 13.06.2016 13:47
def validate_shouldMakeMessageTest() throws Exception {given:
def inputMessage = accurestMessaging.create('''{"bookName":"foo"}'''> ,[ 'sample': 'header' ])
when: accurestMessaging.send(inputMessage,'input')then:
def response = accurestMessaging.receiveMessage('output')assert response != nullresponse.getHeader('BOOK-NAME') == 'foo'
and:DocumentContext parsedJson = JsonPath.parse(accurestObjectMapper
.writeValueAsString(response.payload))assertThatJson(parsedJson).field("bookName").isEqualTo("foo")
}
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
107 z 112 13.06.2016 13:47
io.codearte.accurest.dsl.Accurest.make { description 'Some description' label 'some_label' input { triggeredBy('bookReturnedTriggered()') } outputMessage { sentTo('output') body('''{ "bookName" : "foo" }''') headers { header('BOOK-NAME', 'foo') } } }
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
108 z 112 13.06.2016 13:47
def validate_shouldMakeMessageTest() throws Exception {when:
bookReturnedTriggered()
then:def response = accurestMessaging.receiveMessage('output')assert response != nullresponse.getHeader('BOOK-NAME') == 'foo'
and:DocumentContext parsedJson = JsonPath.parse(accurestObjectMapper
.writeValueAsString(response.payload))assertThatJson(parsedJson).field("bookName").isEqualTo("foo")
}
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
109 z 112 13.06.2016 13:47
Consumer SideConsumer Side
testCompile "io. codearte.accurest:accurest-messaging-camel:${accurestVersion}"
testCompile "io.codearte.accurest:accurest-messaging-integration:${accurestVersion}"
testCompile "io.codearte.accurest:accurest-messaging-stream:${accurestVersion}"
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
110 z 112 13.06.2016 13:47
Possible IssuesPossible Issues
Complex Systems
Test Base Class
Gradle Setup
Young solution
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
111 z 112 13.06.2016 13:47
/ /
Thank youThank you
https://github.com/Codearte/accurest
branch:
08_publish_stubs
https://github.com/OlgaMaciaszek/cdc_examples
branch: 02_with_accurest_rule
https://github.com/OlgaMaciaszek
/LoanApplicationService
Olga Maciaszek-Sharma @olga_maciaszek
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/
112 z 112 13.06.2016 13:47