diff --git a/docker/spring-cloud-contract-docker/get_dependencies.sh b/docker/spring-cloud-contract-docker/get_dependencies.sh index 08accea4e8..33783b5a8c 100755 --- a/docker/spring-cloud-contract-docker/get_dependencies.sh +++ b/docker/spring-cloud-contract-docker/get_dependencies.sh @@ -2,7 +2,7 @@ set -e -WRAPPER_VERSION="7.0" +WRAPPER_VERSION="7.1" GRADLE_BIN_DIR="gradle-${WRAPPER_VERSION}-bin" GRADLE_WRAPPER_DIR="${HOME}/.gradle/wrapper/dists/${GRADLE_BIN_DIR}" CURRENT_DIR="$( pwd )" diff --git a/docker/spring-cloud-contract-docker/project/gradle.properties b/docker/spring-cloud-contract-docker/project/gradle.properties index b31a1a6387..e890e2e583 100644 --- a/docker/spring-cloud-contract-docker/project/gradle.properties +++ b/docker/spring-cloud-contract-docker/project/gradle.properties @@ -1,4 +1,4 @@ org.gradle.daemon=false -verifierVersion=3.0.4-SNAPSHOT -springBootVersion=2.4.7 -camelVersion=3.4.3 \ No newline at end of file +verifierVersion=3.1.0-SNAPSHOT +springBootVersion=2.6.0-SNAPSHOT +camelVersion=3.11.0 \ No newline at end of file diff --git a/pom.xml b/pom.xml index f1a4c9c07b..643ea7d8c6 100644 --- a/pom.xml +++ b/pom.xml @@ -23,10 +23,9 @@ 2016 - - 3.6.0 - 2.17 - 4.0.10 + + 3.11.0 + 4.2.7 0.0.9 3.1.0-SNAPSHOT 3.1.0-SNAPSHOT @@ -43,12 +42,10 @@ 4.2.0 5.5.1.201910021850-r 1 - 3.4.6 - 2.19.0 + 2.27.0 - 1.3.2 - 5.6.2 - 5.5.2 + 5.7.2 + 5.7.2 1.12.1 @@ -63,7 +60,7 @@ 1.6.0 1.3.0 - 1.4.0 + 1.4.31 1.9.4 true @@ -210,8 +207,8 @@ ${commons-text.version} - au.com.dius - pact-jvm-consumer-java8 + au.com.dius.consumer + pact-jvm-consumer ${pact.version} @@ -225,7 +222,7 @@ - au.com.dius + au.com.dius.provider pact-jvm-provider-junit ${pact.version} @@ -459,27 +456,9 @@ kotlin-compiler-embeddable ${contract.kotlin.version} - - - org.mockito - mockito-core - ${mockito.version} - - - - org.junit.vintage - junit-vintage-engine - test - - - - - [3.2.1,) - - Spring https://spring.io/ @@ -494,17 +473,17 @@ marcingrzejszczak Marcin Grzejszczak - mgrzejszczak@pivotal.io + mgrzejszczak@vmware.com dsyer David Syer - dsyer@pivotal.io + dsyer@vmware.com OlgaMaciaszek Olga Maciaszek-Sharma - omaciaszeksharma@pivotal.io + omaciaszeksharma@vmware.com @@ -524,8 +503,8 @@ - CircleCi - https://circleci.com/gh/spring-cloud/spring-cloud-contract + Github Actions + https://github.com/spring-cloud/spring-cloud-contract/actions diff --git a/specs/spring-cloud-contract-spec-java/src/test/groovy/repackaged/nl/flotsam/xeger/XegerTest.java b/specs/spring-cloud-contract-spec-java/src/test/groovy/repackaged/nl/flotsam/xeger/XegerTest.java index 0ba4582534..08be62eed1 100644 --- a/specs/spring-cloud-contract-spec-java/src/test/groovy/repackaged/nl/flotsam/xeger/XegerTest.java +++ b/specs/spring-cloud-contract-spec-java/src/test/groovy/repackaged/nl/flotsam/xeger/XegerTest.java @@ -22,10 +22,10 @@ import java.util.ArrayList; import java.util.List; import java.util.Random; -import org.junit.Test; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import static org.assertj.core.api.Assertions.assertThat; public class XegerTest { @@ -35,7 +35,7 @@ public class XegerTest { Xeger generator = new Xeger(regex); for (int i = 0; i < 100; i++) { String text = generator.generate(); - assertTrue(text.matches(regex)); + assertThat(text.matches(regex)).isTrue(); } } @@ -46,7 +46,7 @@ public class XegerTest { Xeger generator = new Xeger(regex); for (int i = 0; i < 100; i++) { String text = generator.generate(); - assertTrue(text.length() == 1); + assertThat(text.length() == 1).isTrue(); } } @@ -56,7 +56,7 @@ public class XegerTest { Xeger generator = new Xeger(regex); for (int i = 0; i < 100; i++) { String text = generator.generate(); - assertTrue(text.matches(regex)); + assertThat(text.matches(regex)).isTrue(); } } @@ -66,7 +66,7 @@ public class XegerTest { Xeger generator = new Xeger(regex); for (int i = 0; i < 100; i++) { String text = generator.generate(); - assertTrue(text.matches(regex)); + assertThat(text.matches(regex)).isTrue(); } } @@ -76,7 +76,7 @@ public class XegerTest { Xeger generator = new Xeger(regex); for (int i = 0; i < 100; i++) { String text = generator.generate(); - assertTrue(text.matches(regex)); + assertThat(text.matches(regex)).isTrue(); } } @@ -90,7 +90,7 @@ public class XegerTest { List secondRegexList = generateRegex(generator2, 100); for (int i = 0; i < firstRegexList.size(); i++) { - assertEquals("Index mismatch: " + i, firstRegexList.get(i), secondRegexList.get(i)); + assertThat(firstRegexList.get(i)).isEqualTo(secondRegexList.get(i)); } } } diff --git a/specs/spring-cloud-contract-spec-java/src/test/groovy/repackaged/nl/flotsam/xeger/XegerUtilsTest.java b/specs/spring-cloud-contract-spec-java/src/test/groovy/repackaged/nl/flotsam/xeger/XegerUtilsTest.java index eadf3c71fd..8705316413 100644 --- a/specs/spring-cloud-contract-spec-java/src/test/groovy/repackaged/nl/flotsam/xeger/XegerUtilsTest.java +++ b/specs/spring-cloud-contract-spec-java/src/test/groovy/repackaged/nl/flotsam/xeger/XegerUtilsTest.java @@ -20,10 +20,9 @@ package repackaged.nl.flotsam.xeger; import java.util.Random; -import org.hamcrest.Matchers; -import org.junit.Test; +import org.junit.jupiter.api.Test; -import static org.junit.Assert.assertThat; +import static org.assertj.core.api.Assertions.assertThat; public class XegerUtilsTest { @@ -32,8 +31,7 @@ public class XegerUtilsTest { Random random = new Random(); for (int i = 0; i < 100; i++) { int number = Xeger.getRandomInt(3, 7, random); - assertThat(number, Matchers.greaterThanOrEqualTo(3)); - assertThat(number, Matchers.lessThanOrEqualTo(7)); + assertThat(number).isGreaterThanOrEqualTo(3).isLessThanOrEqualTo(7); } } diff --git a/specs/spring-cloud-contract-spec/src/test/groovy/org/springframework/cloud/contract/spec/internal/HttpStatusTests.java b/specs/spring-cloud-contract-spec/src/test/groovy/org/springframework/cloud/contract/spec/internal/HttpStatusTests.java index 0b29c89410..cac73eb81e 100644 --- a/specs/spring-cloud-contract-spec/src/test/groovy/org/springframework/cloud/contract/spec/internal/HttpStatusTests.java +++ b/specs/spring-cloud-contract-spec/src/test/groovy/org/springframework/cloud/contract/spec/internal/HttpStatusTests.java @@ -17,7 +17,7 @@ package org.springframework.cloud.contract.spec.internal; import org.assertj.core.api.BDDAssertions; -import org.junit.Test; +import org.junit.jupiter.api.Test; /** * @author Marcin Grzejszczak diff --git a/spring-cloud-contract-tools/spring-cloud-contract-pact/pom.xml b/spring-cloud-contract-tools/spring-cloud-contract-pact/pom.xml index f268268af0..3cf410f756 100644 --- a/spring-cloud-contract-tools/spring-cloud-contract-pact/pom.xml +++ b/spring-cloud-contract-tools/spring-cloud-contract-pact/pom.xml @@ -39,11 +39,11 @@ groovy-nio - au.com.dius - pact-jvm-consumer-java8 + au.com.dius.consumer + pact-jvm-consumer - au.com.dius + au.com.dius.provider pact-jvm-provider-junit diff --git a/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/util/MetadataUtil.java b/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/util/MetadataUtil.java index 165a83c646..0e2eecd511 100644 --- a/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/util/MetadataUtil.java +++ b/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/util/MetadataUtil.java @@ -22,8 +22,10 @@ import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.Objects; +import java.util.Properties; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; import com.fasterxml.jackson.annotation.JsonFilter; import com.fasterxml.jackson.annotation.JsonInclude; @@ -36,6 +38,11 @@ import com.fasterxml.jackson.databind.ser.PropertyWriter; import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter; import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.config.YamlPropertiesFactoryBean; +import org.springframework.boot.context.properties.bind.Binder; +import org.springframework.boot.context.properties.source.MapConfigurationPropertySource; +import org.springframework.core.io.ByteArrayResource; import org.springframework.util.ReflectionUtils; /** @@ -80,11 +87,29 @@ public final class MetadataUtil { if (patch == null) { return objectToMerge; } + byte[] bytes = new byte[0]; try { - byte[] bytes = MAPPER.writer().writeValueAsBytes(patch); + bytes = MAPPER.writer().writeValueAsBytes(patch); return MAPPER.readerForUpdating(objectToMerge).readValue(bytes); } catch (Exception e) { + if (e.getClass().toString().contains("InaccessibleObjectException") && patch instanceof Map) { + try { + YamlPropertiesFactoryBean yamlProcessor = new YamlPropertiesFactoryBean(); + yamlProcessor.setResources(new ByteArrayResource(bytes)); + Properties properties = yamlProcessor.getObject(); + T props = (T) new Binder( + new MapConfigurationPropertySource(properties.entrySet().stream() + .collect(Collectors.toMap(entry -> entry.getKey().toString(), + entry -> entry.getValue().toString())))).bind("", objectToMerge.getClass()) + .get(); + BeanUtils.copyProperties(props, objectToMerge); + return objectToMerge; + } + catch (Exception ex) { + throw new IllegalStateException(ex); + } + } throw new IllegalStateException(e); } } @@ -207,23 +232,27 @@ class MyFilter extends SimpleBeanPropertyFilter implements Serializable { writer.serializeAsField(pojo, jgen, provider); return; } - Object defaultInstance = CACHE.computeIfAbsent(pojo.getClass(), this::defaultInstance); + Object defaultInstance = defaultInstance(pojo); if (defaultInstance instanceof CantInstantiateThisClass || !valueSameAsDefault(pojo, defaultInstance, writer.getName())) { writer.serializeAsField(pojo, jgen, provider); } } + Object defaultInstance(Object pojo) { + return CACHE.computeIfAbsent(pojo.getClass(), this::defaultInstance); + } + private Object defaultInstance(Class aClass) { try { - return aClass.newInstance(); + return aClass.getDeclaredConstructor().newInstance(); } catch (Exception e) { return new CantInstantiateThisClass(); } } - private boolean valueSameAsDefault(Object pojo, Object defaultInstance, String fieldName) { + boolean valueSameAsDefault(Object pojo, Object defaultInstance, String fieldName) { Field field = ReflectionUtils.findField(pojo.getClass(), fieldName); if (field == null) { return false; diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/SpringTestMethodBodyBuildersSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/SpringTestMethodBodyBuildersSpec.groovy index d76f5a8b76..b016313dc2 100644 --- a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/SpringTestMethodBodyBuildersSpec.groovy +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/SpringTestMethodBodyBuildersSpec.groovy @@ -225,7 +225,7 @@ class SpringTestMethodBodyBuildersSpec extends Specification implements WireMock } private String singleTestGenerator(Contract contractDsl) { - return singleTestGenerator([contractDsl]) + return singleTestGenerator(Collections.singletonList(contractDsl)) } private String singleTestGenerator(Collection contractDsls) { @@ -245,7 +245,7 @@ class SpringTestMethodBodyBuildersSpec extends Specification implements WireMock } }) } - }.buildClass(configProperties, [contractMetadata(contractDsls)], "foo", generatedClassData) + }.buildClass(configProperties, Collections.singletonList(contractMetadata(contractDsls)), "foo", generatedClassData) } ContractMetadata contractMetadata(Collection contractDsls) { diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/converter/YamlContractConverterSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/converter/YamlContractConverterSpec.groovy index f31d54d26a..2b4f8bc1f8 100644 --- a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/converter/YamlContractConverterSpec.groovy +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/converter/YamlContractConverterSpec.groovy @@ -136,22 +136,22 @@ class YamlContractConverterSpec extends Specification { contract.request.url.clientValue == "/foo" contract.request.cookies.entries.find { it.key == "foo" && it.serverValue == "bar" } contract.request.cookies.entries.find { - it.key == "fooRegex" && ((Pattern) it.clientValue).pattern == "reg" && it.serverValue == "reg" + it.key == "fooRegex" && ((Pattern) it.clientValue).pattern() == "reg" && it.serverValue == "reg" } contract.request.cookies.entries.find { - it.key == "fooPredefinedRegex" && ((Pattern) it.clientValue).pattern == "(true|false)" && it.serverValue == true + it.key == "fooPredefinedRegex" && ((Pattern) it.clientValue).pattern() == "(true|false)" && it.serverValue == true } and: contract.response.status.clientValue == 200 contract.response.cookies.entries.find { it.key == "foo" && it.clientValue == "baz" } contract.response.cookies.entries.find { - it.key == "fooRegex" && ((Pattern) it.serverValue).pattern == "[0-9]+" && it.clientValue == 123 + it.key == "fooRegex" && ((Pattern) it.serverValue).pattern() == "[0-9]+" && it.clientValue == 123 } contract.response.cookies.entries.find { - it.key == "source" && ((Pattern) it.serverValue).pattern == "ip_address" && it.clientValue == "ip_address" + it.key == "source" && ((Pattern) it.serverValue).pattern() == "ip_address" && it.clientValue == "ip_address" } contract.response.cookies.entries.find { - it.key == "fooPredefinedRegex" && ((Pattern) it.serverValue).pattern == "(true|false)" && it.clientValue == true + it.key == "fooPredefinedRegex" && ((Pattern) it.serverValue).pattern() == "(true|false)" && it.clientValue == true } MapConverter.getStubSideValues(contract.response.body) == ["status": "OK"] } @@ -178,7 +178,7 @@ class YamlContractConverterSpec extends Specification { contract.request.method.clientValue == "PUT" contract.request.headers.entries.find { it.name == "foo" && - ((Pattern) it.clientValue).pattern == "bar" && it.serverValue == "bar" + ((Pattern) it.clientValue).pattern() == "bar" && it.serverValue == "bar" } contract.request.headers.entries.find { it.name == "fooReq" && @@ -198,7 +198,7 @@ class YamlContractConverterSpec extends Specification { } contract.response.headers.entries.find { it.name == "foo2" && - ((Pattern) it.serverValue).pattern == "bar" && it.clientValue == "bar" + ((Pattern) it.serverValue).pattern() == "bar" && it.clientValue == "bar" } contract.response.headers.entries.find { it.name == "foo3" && @@ -269,7 +269,7 @@ class YamlContractConverterSpec extends Specification { Contract contract = contracts.first() contract.request.headers.entries.find { it.name == "Content-Type" && - ((Pattern) it.clientValue).pattern == "application/json.*" && it.serverValue == "application/json" + ((Pattern) it.clientValue).pattern() == "application/json.*" && it.serverValue == "application/json" } ((Pattern) contract.request.urlPath.clientValue).pattern() == "/get/[0-9]" contract.request.urlPath.serverValue == "/get/1" @@ -404,7 +404,7 @@ class YamlContractConverterSpec extends Specification { Contract contract = contracts.first() contract.input.messageHeaders.entries.find { it.name == "contentType" && - ((Pattern) it.clientValue).pattern == "application/json.*" && it.serverValue == "application/json" + ((Pattern) it.clientValue).pattern() == "application/json.*" && it.serverValue == "application/json" } contract.input.bodyMatchers.matchers[0].path() == '$.duck' contract.input.bodyMatchers.matchers[0].matchingType() == REGEX @@ -539,7 +539,7 @@ class YamlContractConverterSpec extends Specification { contract.input.triggeredBy.toString() == "foo()" contract.input.messageHeaders.entries.find { it.name == "foo" && - ((Pattern) it.clientValue).pattern == "bar" && it.serverValue == "bar" + ((Pattern) it.clientValue).pattern() == "bar" && it.serverValue == "bar" } contract.input.messageBody.clientValue == [foo: "bar"] contract.input.bodyMatchers.matchers[0].path() == '$.bar' @@ -549,7 +549,7 @@ class YamlContractConverterSpec extends Specification { contract.outputMessage.assertThat.toString() == "baz()" contract.outputMessage.headers.entries.find { it.name == "foo2" && - ((Pattern) it.serverValue).pattern == "bar" && it.clientValue == "bar" + ((Pattern) it.serverValue).pattern() == "bar" && it.clientValue == "bar" } contract.outputMessage.headers.entries.find { it.name == "foo3" && diff --git a/spring-cloud-contract-verifier/src/test/java/org/springframework/cloud/contract/verifier/messaging/amqp/AmqpMetadataTests.java b/spring-cloud-contract-verifier/src/test/java/org/springframework/cloud/contract/verifier/messaging/amqp/AmqpMetadataTests.java index a006b4d9dc..380f35fdc0 100644 --- a/spring-cloud-contract-verifier/src/test/java/org/springframework/cloud/contract/verifier/messaging/amqp/AmqpMetadataTests.java +++ b/spring-cloud-contract-verifier/src/test/java/org/springframework/cloud/contract/verifier/messaging/amqp/AmqpMetadataTests.java @@ -25,7 +25,7 @@ import static org.assertj.core.api.BDDAssertions.then; class AmqpMetadataTests { YAMLMapper mapper = new YAMLMapper(); - + @Test void should_parse_the_metadata_entry() throws JsonProcessingException { // @formatter:off