diff --git a/docs/src/main/asciidoc/verifier/contract.adoc b/docs/src/main/asciidoc/verifier/contract.adoc index c0829b7f86..55a18fcc9b 100644 --- a/docs/src/main/asciidoc/verifier/contract.adoc +++ b/docs/src/main/asciidoc/verifier/contract.adoc @@ -226,7 +226,21 @@ include::{plugins_path}/spring-cloud-contract-converters/src/test/groovy/org/spr ====== Executing custom methods on server side It is also possible to define a method call to be executed on the server side during the test. Such a method can be added to the class defined as "baseClassForTests" -in the configuration. Please see the examples below: +in the configuration. Example: + +*Contract* + +[source,groovy,indent=0] +---- +include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/ContractHttpDocsSpec.groovy[tags=method,indent=0] +---- + +*Base class* + +[source,groovy,indent=0] +---- +include::{plugins_path}/spring-cloud-contract-gradle-plugin/src/test/resources/functionalTest/bootSimple/src/test/groovy/org/springframework/cloud/contract/verifier/twitter/places/BaseMockMvcSpec.groovy[tags=base_class,indent=0] +---- ===== Dynamic properties in matchers sections @@ -332,22 +346,8 @@ and the WireMock stub like this: include::{plugins_path}/spring-cloud-contract-converters/src/test/groovy/org/springframework/cloud/contract/verifier/wiremock/DslToWireMockClientConverterSpec.groovy[tags=matchers,indent=0] ---- - -===== Contract DSL - -[source,groovy,indent=0] ----- -include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/ContractHttpDocsSpec.groovy[tags=method,indent=0] ----- - -===== Base Mock Spec - -[source,groovy,indent=0] ----- -include::{plugins_path}/spring-cloud-contract-gradle-plugin/src/test/resources/functionalTest/bootSimple/src/test/groovy/org/springframework/cloud/contract/verifier/twitter/places/BaseMockMvcSpec.groovy[tags=base_class,indent=0] ----- - ==== JAX-RS support + Starting with release 0.8.0 we support JAX-RS 2 Client API. Base class needs to define `protected WebTarget webTarget` and server initialization, right now the only option how to test JAX-RS API is to start a web server. Request with a body needs to have a content type set otherwise `application/octet-stream` is going to be used. diff --git a/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/internal/BodyMatchers.groovy b/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/internal/BodyMatchers.groovy index fb8a9d3248..ef25c44d67 100644 --- a/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/internal/BodyMatchers.groovy +++ b/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/internal/BodyMatchers.groovy @@ -4,6 +4,7 @@ import groovy.transform.Canonical import groovy.transform.CompileStatic import groovy.transform.EqualsAndHashCode import groovy.transform.ToString + /** * Matching strategy of dynamic parts of the body. * @@ -11,6 +12,7 @@ import groovy.transform.ToString * @since 1.0.3 */ @CompileStatic +@ToString(includeFields = true, includePackage = false) class BodyMatchers { private final RegexPatterns regexPatterns = new RegexPatterns() private final List jsonPathRegexMatchers = [] @@ -43,9 +45,24 @@ class BodyMatchers { assert regex return new MatchingTypeValue(MatchingType.REGEX, regex) } + + boolean equals(o) { + if (this.is(o)) return true + if (this.getClass() != o.class) return false + BodyMatchers that = (BodyMatchers) o + List thisMatchers = this.jsonPathRegexMatchers + List thatMatchers = that.jsonPathRegexMatchers + if (thisMatchers.size() != thatMatchers.size()) return false + if (new HashSet<>(thisMatchers) != new HashSet(thatMatchers)) return false + return true + } + + int hashCode() { + return (this.jsonPathRegexMatchers != null ? this.jsonPathRegexMatchers.hashCode() : 0) + } } -@ToString +@ToString(includePackage = false) @EqualsAndHashCode @Canonical @CompileStatic @@ -83,6 +100,8 @@ class JsonPathBodyMatcher implements BodyMatcher { * Matching type with corresponding values */ @Canonical +@ToString(includePackage = false) +@EqualsAndHashCode class MatchingTypeValue { MatchingType type diff --git a/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/internal/RegexPatterns.groovy b/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/internal/RegexPatterns.groovy index 8af7f580e8..a721f64ab4 100644 --- a/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/internal/RegexPatterns.groovy +++ b/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/internal/RegexPatterns.groovy @@ -17,14 +17,19 @@ package org.springframework.cloud.contract.spec.internal import groovy.transform.CompileStatic +import groovy.transform.EqualsAndHashCode +import groovy.transform.ToString import java.util.regex.Pattern + /** * Contains most common regular expression patterns * * @since 1.0.0 */ @CompileStatic +@EqualsAndHashCode +@ToString(includePackage = false) class RegexPatterns { // tag::regexps[] diff --git a/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/internal/ResponseBodyMatchers.groovy b/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/internal/ResponseBodyMatchers.groovy index ef9eaf9ab2..b890e23f20 100644 --- a/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/internal/ResponseBodyMatchers.groovy +++ b/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/internal/ResponseBodyMatchers.groovy @@ -11,24 +11,26 @@ import groovy.transform.ToString * @since 1.0.3 */ @CompileStatic -@EqualsAndHashCode -@ToString(includePackage = false) +@ToString(includePackage = false, includeSuper = true) class ResponseBodyMatchers extends BodyMatchers { MatchingTypeValue byType() { - return new MatchingTypeValue(MatchingType.TYPE) + return new MatchingTypeValue(type: MatchingType.TYPE) } MatchingTypeValue byType(@DelegatesTo(MatchingTypeValueHolder) Closure closure) { MatchingTypeValueHolder matchingTypeValue = new MatchingTypeValueHolder() closure.delegate = matchingTypeValue - return closure() as MatchingTypeValue + closure() + return matchingTypeValue.matchingTypeValue } } @CompileStatic +@ToString(includePackage = false) +@EqualsAndHashCode class MatchingTypeValueHolder { - MatchingTypeValue matchingTypeValue = new MatchingTypeValue() + MatchingTypeValue matchingTypeValue = new MatchingTypeValue(type: MatchingType.TYPE) MatchingTypeValue minOccurrence(int number) { this.matchingTypeValue.minTypeOccurrence = number