Creating and testing REST contracts with Accurest Gradle

50 %
50 %
Information about Creating and testing REST contracts with Accurest Gradle

Published on June 14, 2016

Author: gr8conf

Source: slideshare.net

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

2. / oms@codearte.io@olga_maciaszek Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/ 2 z 112 13.06.2016 13:47

3. 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

4. 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

5. 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

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

7. 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

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

9. 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

10. 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

11. 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

12. 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

13. 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

14. 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

15. 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

16. 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

17. 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

18. 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

19. 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

20. 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

21. 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

22. 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

23. 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

24. 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

25. 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

26. 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

27. 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

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

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

30. 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

31. 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

32. 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

33. 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

34. 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

35. 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

36. 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

37. 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

38. 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

39. 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

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

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

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

43. { "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

44. { "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

45. 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

46. { "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

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

48. { "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

49. 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

50. { "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

51. 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

52. { "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

53. { "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

54. 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

55. { "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

56. 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

57. { "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

58. 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

59. { "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

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

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

62. 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

63. 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

64. 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

65. 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

66. 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

67. 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

68. 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

69. 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

70. 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

71. 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

72. 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

73. 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

74. Base Test ClassBase Test Class class BaseMockMvcSpec extends Specification { def setup() { RestAssuredMockMvc.standaloneSetup(new PairIdController()) } } @ContextConfiguration(classes = [PaymentResourceStubContext, ClientResourceStubContext], loader = SpringApplicationContextLoader) @WebIntegrationTest class 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

75. 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

76. 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

77. { "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

78. 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

79. 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

80. 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

81. 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

82. 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

83. 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

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

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

86. 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

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

88. 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

89. 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

90. 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

91. 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

92. 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

93. 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

94. 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

95. 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 != null response.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

96. 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

97. 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 != null response.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

98. 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

99. 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 != null response.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

100. 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

101. 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 != null response.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

102. 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

103. 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 != null response.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

104. 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

105. 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 != null response.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

106. 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

107. 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 != null response.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

108. 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

109. def validate_shouldMakeMessageTest() throws Exception { when: bookReturnedTriggered() then: def response = accurestMessaging.receiveMessage('output') assert response != null response.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

110. 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

111. 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

112. / / 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 oms@codearte.io Creating and Testing REST and Messaging Contracts with Accurest http://localhost:8000/?print-pdf#/ 112 z 112 13.06.2016 13:47

Add a comment

Related pages

Creating and testing REST contracts with Accurest Gradle ...

REST does not come with an in-built contract compliance mechanism, which in many ways is a great thing (no cumbersome xml schemas). However, while working ...
Read more

Creating and testing REST contracts with Accurest Gradle ...

REST does not come with an in-built contract compliance mechanism, which in many ways is a great thing. However, while working with microservice ...
Read more

Creating and testing REST contracts with Accurest Gradle

Creating and testing REST contracts with Accurest Gradle. Embedded from: ... I will present Accurest, a Gradle plugin that allows for both: ...
Read more

Agenda 2016 » Greach

Agenda 2016 Greach 2016. ... Testing In Grails 3 Jeff Brown: ... Creating and testing REST contracts with Accurest Gradle Plugin
Read more

Grails Diary - Week 18 in 2016 - Jacob Aae Mikkelsen

Grails Diary - Week 18 in 2016 09-05-2016. ... Creating and testing REST contracts with Accurest Gradle Plugin ... Gradle Glam: Plugins Galore ...
Read more

今週のGrails 2016-18

Creating and testing REST contracts with Accurest Gradle Plugin ... Creating AST's the painful truth? ... @gradle "Get a list of #Gradle books in English, ...
Read more

This week in API land #51 | Restlet - We Know About APIs

Web-based API testing. User Guide; ... on creating and testing REST contracts with the Accurest Gradle ... that follow the REST API ...
Read more

Production Line OEE (Overall Equipment Effectiveness)

Creating and testing REST contracts with Accurest Gradle. By: slideshare . Providing the best service for the F-Secure Antivirus.(800) 294-5907. Embed slide.
Read more

Greach 2016 - Olga Maciaszek Sharma - Creating and testing ...

REST does not come with an in-built contract compliance mechanism, which in many ways is a great thing (no cumbersome xml schemas). However ...
Read more