creating and testing rest contracts with accurest gradle

112
Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/ 1 z 112 13.06.2016 13:47

Upload: gr8conf

Post on 16-Jan-2017

392 views

Category:

Technology


0 download

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

[email protected]

Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/

112 z 112 13.06.2016 13:47