From de70cd1ef6c197c036eba09d9573c09a82f6d532 Mon Sep 17 00:00:00 2001 From: Artem Ptushkin Date: Thu, 27 Jun 2019 16:00:56 +0300 Subject: [PATCH] Matching strategy at body and contentType issue (#1113) * Created test for equalToXml and bodyMatchers with xml content type - Failed * Fixed equalToXml at stub for the equalToXml body and xml content type * Fixed equalToJson at stub for the equalToJson body and explicit json content type. If body has matching strategy then it has be used for stub generation. --- .../WireMockRequestStubStrategy.groovy | 88 ++++++++---------- .../dsl/wiremock/WireMockGroovyDslSpec.groovy | 93 +++++++++++++++++++ 2 files changed, 130 insertions(+), 51 deletions(-) diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/dsl/wiremock/WireMockRequestStubStrategy.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/dsl/wiremock/WireMockRequestStubStrategy.groovy index fe90c12b3c..80413bef0b 100755 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/dsl/wiremock/WireMockRequestStubStrategy.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/dsl/wiremock/WireMockRequestStubStrategy.groovy @@ -16,48 +16,24 @@ package org.springframework.cloud.contract.verifier.dsl.wiremock -import java.util.regex.Pattern - import com.github.tomakehurst.wiremock.client.WireMock import com.github.tomakehurst.wiremock.http.RequestMethod -import com.github.tomakehurst.wiremock.matching.ContentPattern -import com.github.tomakehurst.wiremock.matching.RequestPattern -import com.github.tomakehurst.wiremock.matching.RequestPatternBuilder -import com.github.tomakehurst.wiremock.matching.StringValuePattern -import com.github.tomakehurst.wiremock.matching.UrlPattern +import com.github.tomakehurst.wiremock.matching.* import groovy.json.JsonOutput import groovy.json.StringEscapeUtils import groovy.transform.PackageScope import groovy.transform.TypeChecked import groovy.transform.TypeCheckingMode import groovy.util.logging.Commons - import org.springframework.cloud.contract.spec.Contract -import org.springframework.cloud.contract.spec.internal.Body -import org.springframework.cloud.contract.spec.internal.BodyMatcher -import org.springframework.cloud.contract.spec.internal.DslProperty -import org.springframework.cloud.contract.spec.internal.FromFileProperty -import org.springframework.cloud.contract.spec.internal.MatchingStrategy -import org.springframework.cloud.contract.spec.internal.MatchingType -import org.springframework.cloud.contract.spec.internal.NamedProperty -import org.springframework.cloud.contract.spec.internal.OptionalProperty -import org.springframework.cloud.contract.spec.internal.PathBodyMatcher -import org.springframework.cloud.contract.spec.internal.QueryParameters -import org.springframework.cloud.contract.spec.internal.RegexPatterns -import org.springframework.cloud.contract.spec.internal.RegexProperty -import org.springframework.cloud.contract.spec.internal.Request -import org.springframework.cloud.contract.verifier.util.ContentType -import org.springframework.cloud.contract.verifier.util.ContentUtils -import org.springframework.cloud.contract.verifier.util.JsonPaths -import org.springframework.cloud.contract.verifier.util.JsonToJsonPathsConverter -import org.springframework.cloud.contract.verifier.util.MapConverter +import org.springframework.cloud.contract.spec.internal.* +import org.springframework.cloud.contract.verifier.util.* import org.springframework.cloud.contract.verifier.util.xml.XmlToXPathsConverter +import java.util.regex.Pattern + import static org.springframework.cloud.contract.spec.internal.MatchingStrategy.Type.BINARY_EQUAL_TO -import static org.springframework.cloud.contract.spec.internal.MatchingType.COMMAND -import static org.springframework.cloud.contract.spec.internal.MatchingType.EQUALITY -import static org.springframework.cloud.contract.spec.internal.MatchingType.NULL -import static org.springframework.cloud.contract.spec.internal.MatchingType.TYPE +import static org.springframework.cloud.contract.spec.internal.MatchingType.* import static org.springframework.cloud.contract.verifier.util.ContentType.FORM import static org.springframework.cloud.contract.verifier.util.ContentUtils.getEqualsTypeFromContentType import static org.springframework.cloud.contract.verifier.util.RegexpBuilders.buildGStringRegexpForStubSide @@ -115,24 +91,29 @@ class WireMockRequestStubStrategy extends BaseWireMockStubStrategy { if (!request.body) { return } + boolean bodyHasMatchingStrategy = request.body.clientValue instanceof MatchingStrategy MatchingStrategy matchingStrategy = getMatchingStrategyFromBody(request.body) if (contentType == ContentType.JSON) { def originalBody = matchingStrategy?.clientValue - def body = JsonToJsonPathsConverter. - removeMatchingJsonPaths(originalBody, request.bodyMatchers) - JsonPaths values = JsonToJsonPathsConverter. - transformToJsonPathWithStubsSideValuesAndNoArraySizeCheck(body) - if ((values.empty && !request.bodyMatchers?.hasMatchers()) - || - onlySizeAssertionsArePresent(values)) { - requestPattern.withRequestBody(WireMock.equalToJson(JsonOutput.toJson( - getMatchingStrategy(request.body.clientValue).clientValue), - false, false)) - } - else { - values.findAll { !it.assertsSize() }.each { - requestPattern.withRequestBody(WireMock. - matchingJsonPath(it.jsonPath().replace("\\\\", "\\"))) + if (bodyHasMatchingStrategy) { + requestPattern.withRequestBody( + convertToValuePattern(matchingStrategy)) + } else { + def body = JsonToJsonPathsConverter. + removeMatchingJsonPaths(originalBody, request.bodyMatchers) + JsonPaths values = JsonToJsonPathsConverter. + transformToJsonPathWithStubsSideValuesAndNoArraySizeCheck(body) + if ((values.empty && !request.bodyMatchers?.hasMatchers()) + || + onlySizeAssertionsArePresent(values)) { + requestPattern.withRequestBody(WireMock.equalToJson(JsonOutput.toJson( + getMatchingStrategy(request.body.clientValue).clientValue), + false, false)) + } else { + values.findAll { !it.assertsSize() }.each { + requestPattern.withRequestBody(WireMock. + matchingJsonPath(it.jsonPath().replace("\\\\", "\\"))) + } } } request.bodyMatchers?.matchers()?.each { @@ -144,12 +125,17 @@ class WireMockRequestStubStrategy extends BaseWireMockStubStrategy { } else if (contentType == ContentType.XML) { Object originalBody = matchingStrategy?.clientValue - Object body = XmlToXPathsConverter - .removeMatchingXPaths(originalBody, request.bodyMatchers) - List byEqualityMatchersFromXml = new XmlToXPathsConverter() - .mapToMatchers(body) - byEqualityMatchersFromXml.each { - addWireMockStubMatchingSection(it, requestPattern, originalBody) + if (bodyHasMatchingStrategy) { + requestPattern.withRequestBody( + convertToValuePattern(matchingStrategy)) + } else { + Object body = XmlToXPathsConverter + .removeMatchingXPaths(originalBody, request.bodyMatchers) + List byEqualityMatchersFromXml = new XmlToXPathsConverter() + .mapToMatchers(body) + byEqualityMatchersFromXml.each { + addWireMockStubMatchingSection(it, requestPattern, originalBody) + } } request.bodyMatchers?.matchers()?.each { addWireMockStubMatchingSection(it, requestPattern, originalBody) diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/dsl/wiremock/WireMockGroovyDslSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/dsl/wiremock/WireMockGroovyDslSpec.groovy index e4164fefe7..5d4ebcd747 100755 --- a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/dsl/wiremock/WireMockGroovyDslSpec.groovy +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/dsl/wiremock/WireMockGroovyDslSpec.groovy @@ -568,6 +568,51 @@ class WireMockGroovyDslSpec extends Specification implements WireMockStubVerifie stubMappingIsValidWireMockStub(json) } + def 'should use equalToJson and bodyMatchers with json content type'() { + given: + org.springframework.cloud.contract.spec.Contract groovyDsl = org.springframework.cloud.contract.spec.Contract.make { + request { + method 'GET' + url "/users" + headers { + header 'Content-Type': 'application/json' + } + body equalToJson('''{"name":"Jan"}''') + bodyMatchers { + jsonPath('$.name', byRegex('[A-Z]{3}')) + } + } + response { + status OK() + } + } + when: + String json = toWireMockClientJsonStub(groovyDsl) + then: + AssertionUtil.assertThatJsonsAreEqual((''' + { + "request": { + "method": "GET", + "url": "/users", + "bodyPatterns": [ + { + "equalToJson":"{\\"name\\":\\"Jan\\"}" + }, + { + "matchesJsonPath" : "$[?(@.name =~ /([A-Z]{3})/)]" + } + ] + }, + "response": { + "status": 200, + "transformers" : [ "response-template", "foo-transformer" ] + } + } + '''), json) + and: + stubMappingIsValidWireMockStub(json) + } + def 'should use equalToXml'() { given: org.springframework.cloud.contract.spec.Contract groovyDsl = org.springframework.cloud.contract.spec.Contract.make { @@ -606,6 +651,54 @@ class WireMockGroovyDslSpec extends Specification implements WireMockStubVerifie stubMappingIsValidWireMockStub(json) } + def 'should use equalToXml and bodyMatchers with xml content type'() { + given: + org.springframework.cloud.contract.spec.Contract groovyDsl = org.springframework.cloud.contract.spec.Contract.make { + request { + method 'GET' + url "/users" + headers { + header "Content-Type", "customtype/xml" + } + body equalToXml( + """${value(consumer('Jozo'), + producer('Denis'))}1234567890""" + ) + bodyMatchers { + xPath('/foo/jobId/text()', byRegex('[0-9]{10}')) + } + } + response { + status OK() + } + } + when: + String json = toWireMockClientJsonStub(groovyDsl) + then: + AssertionUtil.assertThatJsonsAreEqual((''' + { + "request": { + "method": "GET", + "url": "/users", + "bodyPatterns" : [ { + "equalToXml" : "Jozo1234567890" + }, { + "matchesXPath" : { + "expression" : "/foo/jobId/text()", + "matches" : "[0-9]{10}" + } + } ] + }, + "response": { + "status": 200, + "transformers" : [ "response-template", "foo-transformer" ] + } + } + '''), json) + and: + stubMappingIsValidWireMockStub(json) + } + def 'should create stub with body from the file'() { given: org.springframework.cloud.contract.spec.Contract groovyDsl = org.springframework.cloud.contract.spec.Contract.make {