diff --git a/pact/pact-feign-consumer/build.gradle b/pact/pact-feign-consumer/build.gradle index ce384c7..c16d12f 100644 --- a/pact/pact-feign-consumer/build.gradle +++ b/pact/pact-feign-consumer/build.gradle @@ -1,5 +1,3 @@ -apply plugin: 'org.springframework.boot' - buildscript { repositories { mavenLocal() @@ -10,18 +8,43 @@ buildscript { } } +plugins { + id "au.com.dius.pact" version "3.5.20" +} + +apply plugin: 'java' +apply plugin: 'org.springframework.boot' +apply plugin: 'io.spring.dependency-management' + +version '1.0.0.SNAPSHOT' repositories { mavenLocal() jcenter() } +dependencyManagement { + imports { + mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springcloud_version}" + } +} + dependencies { - compile("org.springframework.boot:spring-boot-starter-data-jpa:${springboot_version}") - compile("org.springframework.boot:spring-boot-starter-web:${springboot_version}") - compile("org.springframework.cloud:spring-cloud-starter-feign:1.4.1.RELEASE") + compile('org.springframework.boot:spring-boot-starter-data-jpa') + compile('org.springframework.boot:spring-boot-starter-web') + compile('org.springframework.cloud:spring-cloud-starter-openfeign') + compile('org.springframework.cloud:spring-cloud-starter-netflix-ribbon') compile('com.h2database:h2:1.4.196') testCompile('org.codehaus.groovy:groovy-all:2.4.6') - testCompile("au.com.dius:pact-jvm-consumer-junit_2.11:3.5.2") - testCompile("org.springframework.boot:spring-boot-starter-test:${springboot_version}") + testCompile("au.com.dius:pact-jvm-consumer-junit5_2.12:${pact_version}") + testCompile('org.springframework.boot:spring-boot-starter-test') } + +pact { + publish { + pactDirectory = 'target/pacts' + pactBrokerUrl = 'URL' + pactBrokerUsername = 'USERNAME' + pactBrokerPassword = 'PASSWORD' + } +} \ No newline at end of file diff --git a/pact/pact-feign-consumer/gradle.properties b/pact/pact-feign-consumer/gradle.properties index f4f35f0..10ea871 100644 --- a/pact/pact-feign-consumer/gradle.properties +++ b/pact/pact-feign-consumer/gradle.properties @@ -1,2 +1,3 @@ -springboot_version=1.5.9.RELEASE -verifier_version=1.2.2.RELEASE \ No newline at end of file +springboot_version=2.0.4.RELEASE +springcloud_version=Finchley.SR1 +pact_version=3.5.20 \ No newline at end of file diff --git a/pact/pact-feign-consumer/src/main/java/io/reflectoring/ConsumerApplication.java b/pact/pact-feign-consumer/src/main/java/io/reflectoring/ConsumerApplication.java index bfdec7b..3b9b315 100644 --- a/pact/pact-feign-consumer/src/main/java/io/reflectoring/ConsumerApplication.java +++ b/pact/pact-feign-consumer/src/main/java/io/reflectoring/ConsumerApplication.java @@ -2,10 +2,12 @@ package io.reflectoring; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.cloud.netflix.feign.EnableFeignClients; +import org.springframework.cloud.netflix.ribbon.RibbonClient; +import org.springframework.cloud.openfeign.EnableFeignClients; @SpringBootApplication @EnableFeignClients +@RibbonClient(name = "userservice", configuration = RibbonConfiguration.class) public class ConsumerApplication { public static void main(String[] args) { diff --git a/pact/pact-feign-consumer/src/main/java/io/reflectoring/RibbonConfiguration.java b/pact/pact-feign-consumer/src/main/java/io/reflectoring/RibbonConfiguration.java new file mode 100644 index 0000000..fb6c87a --- /dev/null +++ b/pact/pact-feign-consumer/src/main/java/io/reflectoring/RibbonConfiguration.java @@ -0,0 +1,15 @@ +package io.reflectoring; + +import com.netflix.client.config.IClientConfig; +import com.netflix.loadbalancer.IRule; +import com.netflix.loadbalancer.RandomRule; +import org.springframework.context.annotation.Bean; + +public class RibbonConfiguration { + + @Bean + public IRule ribbonRule(IClientConfig config) { + return new RandomRule(); + } + +} diff --git a/pact/pact-feign-consumer/src/main/java/io/reflectoring/UserClient.java b/pact/pact-feign-consumer/src/main/java/io/reflectoring/UserClient.java index de9ea41..fb54a24 100644 --- a/pact/pact-feign-consumer/src/main/java/io/reflectoring/UserClient.java +++ b/pact/pact-feign-consumer/src/main/java/io/reflectoring/UserClient.java @@ -1,6 +1,6 @@ package io.reflectoring; -import org.springframework.cloud.netflix.feign.FeignClient; +import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; diff --git a/pact/pact-feign-consumer/src/test/java/io/reflectoring/UserServiceConsumerTest.java b/pact/pact-feign-consumer/src/test/java/io/reflectoring/UserServiceConsumerTest.java index 0134ceb..fa8b113 100644 --- a/pact/pact-feign-consumer/src/test/java/io/reflectoring/UserServiceConsumerTest.java +++ b/pact/pact-feign-consumer/src/test/java/io/reflectoring/UserServiceConsumerTest.java @@ -1,83 +1,85 @@ package io.reflectoring; import au.com.dius.pact.consumer.Pact; -import au.com.dius.pact.consumer.PactProviderRuleMk2; -import au.com.dius.pact.consumer.PactVerification; import au.com.dius.pact.consumer.dsl.PactDslJsonBody; import au.com.dius.pact.consumer.dsl.PactDslWithProvider; +import au.com.dius.pact.consumer.junit5.PactConsumerTestExt; +import au.com.dius.pact.consumer.junit5.PactTestFor; import au.com.dius.pact.model.RequestResponsePact; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; -import static org.assertj.core.api.Assertions.assertThat; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import static org.assertj.core.api.Assertions.*; -@RunWith(SpringRunner.class) -@SpringBootTest(properties = { - // overriding provider address - "userservice.ribbon.listOfServers: localhost:8888" +@ExtendWith(PactConsumerTestExt.class) +@ExtendWith(SpringExtension.class) +@PactTestFor(providerName = "userservice", port = "8888") +@SpringBootTest({ + // overriding provider address + "userservice.ribbon.listOfServers: localhost:8888" }) -public class UserServiceConsumerTest { +class UserServiceConsumerTest { - @Rule - public PactProviderRuleMk2 stubProvider = new PactProviderRuleMk2("userservice", "localhost", 8888, this); + @Autowired + private UserClient userClient; - @Autowired - private UserClient userClient; + @Pact(state = "provider accepts a new person", provider = "userservice", consumer = "userclient") + RequestResponsePact createPersonPact(PactDslWithProvider builder) { + // @formatter:off + return builder + .given("provider accepts a new person") + .uponReceiving("a request to POST a person") + .path("/user-service/users") + .method("POST") + .willRespondWith() + .status(201) + .matchHeader("Content-Type", "application/json") + .body(new PactDslJsonBody() + .integerType("id", 42)) + .toPact(); + // @formatter:on + } - @Pact(state = "provider accepts a new person", provider = "userservice", consumer = "userclient") - public RequestResponsePact createPersonPact(PactDslWithProvider builder) { - return builder - .given("provider accepts a new person") - .uponReceiving("a request to POST a person") - .path("/user-service/users") - .method("POST") - .willRespondWith() - .status(201) - .matchHeader("Content-Type", "application/json") - .body(new PactDslJsonBody() - .integerType("id", 42)) - .toPact(); - } - - @Pact(state = "person 42 exists", provider = "userservice", consumer = "userclient") - public RequestResponsePact updatePersonPact(PactDslWithProvider builder) { - return builder - .given("person 42 exists") - .uponReceiving("a request to PUT a person") - .path("/user-service/users/42") - .method("PUT") - .willRespondWith() - .status(200) - .matchHeader("Content-Type", "application/json") - .body(new PactDslJsonBody() - .stringType("firstName", "Zaphod") - .stringType("lastName", "Beeblebrox")) - .toPact(); - } + @Pact(state = "person 42 exists", provider = "userservice", consumer = "userclient") + RequestResponsePact updatePersonPact(PactDslWithProvider builder) { + // @formatter:off + return builder + .given("person 42 exists") + .uponReceiving("a request to PUT a person") + .path("/user-service/users/42") + .method("PUT") + .willRespondWith() + .status(200) + .matchHeader("Content-Type", "application/json") + .body(new PactDslJsonBody() + .stringType("firstName", "Zaphod") + .stringType("lastName", "Beeblebrox")) + .toPact(); + // @formatter:on + } - @Test - @PactVerification(fragment = "createPersonPact") - public void verifyCreatePersonPact() { - User user = new User(); - user.setFirstName("Zaphod"); - user.setLastName("Beeblebrox"); - IdObject id = userClient.createUser(user); - assertThat(id.getId()).isEqualTo(42); - } + @Test + @PactTestFor(pactMethod = "createPersonPact") + void verifyCreatePersonPact() { + User user = new User(); + user.setFirstName("Zaphod"); + user.setLastName("Beeblebrox"); + IdObject id = userClient.createUser(user); + assertThat(id.getId()).isEqualTo(42); + } - @Test - @PactVerification(fragment = "updatePersonPact") - public void verifyUpdatePersonPact() { - User user = new User(); - user.setFirstName("Zaphod"); - user.setLastName("Beeblebrox"); - User updatedUser = userClient.updateUser(42L, user); - assertThat(updatedUser.getFirstName()).isEqualTo("Zaphod"); - assertThat(updatedUser.getLastName()).isEqualTo("Beeblebrox"); - } + @Test + @PactTestFor(pactMethod = "updatePersonPact") + void verifyUpdatePersonPact() { + User user = new User(); + user.setFirstName("Zaphod"); + user.setLastName("Beeblebrox"); + User updatedUser = userClient.updateUser(42L, user); + assertThat(updatedUser.getFirstName()).isEqualTo("Zaphod"); + assertThat(updatedUser.getLastName()).isEqualTo("Beeblebrox"); + } } diff --git a/pact/pact-feign-consumer/target/pacts/userclient-userservice.json b/pact/pact-feign-consumer/target/pacts/userclient-userservice.json new file mode 100644 index 0000000..a73a8f4 --- /dev/null +++ b/pact/pact-feign-consumer/target/pacts/userclient-userservice.json @@ -0,0 +1,115 @@ +{ + "provider": { + "name": "userservice" + }, + "consumer": { + "name": "userclient" + }, + "interactions": [ + { + "description": "a request to PUT a person", + "request": { + "method": "PUT", + "path": "/user-service/users/42" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/json" + }, + "body": { + "firstName": "Zaphod", + "lastName": "Beeblebrox" + }, + "matchingRules": { + "body": { + "$.firstName": { + "matchers": [ + { + "match": "type" + } + ], + "combine": "AND" + }, + "$.lastName": { + "matchers": [ + { + "match": "type" + } + ], + "combine": "AND" + } + }, + "header": { + "Content-Type": { + "matchers": [ + { + "match": "regex", + "regex": "application/json" + } + ], + "combine": "AND" + } + } + } + }, + "providerStates": [ + { + "name": "person 42 exists" + } + ] + }, + { + "description": "a request to POST a person", + "request": { + "method": "POST", + "path": "/user-service/users" + }, + "response": { + "status": 201, + "headers": { + "Content-Type": "application/json" + }, + "body": { + "id": 42 + }, + "matchingRules": { + "header": { + "Content-Type": { + "matchers": [ + { + "match": "regex", + "regex": "application/json" + } + ], + "combine": "AND" + } + }, + "body": { + "$.id": { + "matchers": [ + { + "match": "integer" + } + ], + "combine": "AND" + } + } + } + }, + "providerStates": [ + { + "name": "provider accepts a new person" + } + ] + } + ], + "metadata": { + "pactSpecification": { + "version": "3.0.0" + }, + "pact-jvm": { + "version": "3.5.20" + } + } +} \ No newline at end of file