fix #1656: Add missing support for JSON values inside arrays in WireMockStub (#1764)

Fixes #1656.
Currently, numbers, booleans and null inside arrays are double-quoted
when converting dsl into stub, which results in generating incorrect
json stubs for WireMock. This commit fixes it.
This commit is contained in:
Koki Igarashi
2022-03-24 22:53:47 +09:00
committed by GitHub
parent 5b7fef0f74
commit 9980eb0e9d
3 changed files with 119 additions and 3 deletions

View File

@@ -1134,4 +1134,64 @@ class DslToWireMockClientConverterSpec extends Specification {
return stubMapping
}
@Issue("1656")
def "should convert DSL file to WireMock JSON with array"() {
given:
def converter = new DslToWireMockClientConverter()
and:
File file = tmpFolder.newFile("dsl1656.groovy")
file.write('''
org.springframework.cloud.contract.spec.Contract.make {
request {
method "GET"
url "/api/foo/61923376"
headers {
accept 'application/json'
}
}
response {
status OK()
headers {
contentType(applicationJson())
}
//language=JSON
body(
"""
[
813146,
814952,
813102,
813282
]
"""
)
}
}
''')
when:
String json = converter.convertContents("Test", new ContractMetadata(file.toPath(), false, 0, null,
ContractVerifierDslConverter.convertAsCollection(new File("/"), file))).values().first()
then:
JSONAssert.assertEquals('''
{
"request" : {
"url" : "/api/foo/61923376",
"method" : "GET",
"headers" : {
"Accept" : {
"matches" : "application/json.*"
}
}
},
"response" : {
"status" : 200,
"body" : "[813146,814952,813102,813282]",
"headers" : {
"Content-Type" : "application/json"
},
"transformers" : [ "response-template", "spring-cloud-contract" ]
}
}''', json, false)
}
}

View File

@@ -95,8 +95,15 @@ abstract class BaseWireMockStubStrategy {
/**
* For the given {@link ContentType} returns the Boolean version of the body.
*/
String parseBody(Boolean value, ContentType contentType) {
return value.toString();
Boolean parseBody(Boolean value, ContentType contentType) {
return value;
}
/**
* For the given {@link ContentType} returns the Number version of the body.
*/
Number parseBody(Number value, ContentType contentType) {
return value;
}
/**
@@ -156,6 +163,15 @@ abstract class BaseWireMockStubStrategy {
else if (l instanceof List) {
result.add(parseBody((List<?>) l, contentType));
}
else if (l instanceof Boolean) {
result.add(parseBody((Boolean) l, contentType));
}
else if (l instanceof Number) {
result.add(parseBody((Number) l, contentType));
}
else if (l == null) {
result.add(null);
}
else {
result.add(parseBody(l, contentType));
}

View File

@@ -18,7 +18,6 @@ package org.springframework.cloud.contract.verifier.dsl.wiremock
import groovy.json.JsonSlurper
import org.springframework.cloud.contract.spec.Contract
import org.springframework.cloud.contract.verifier.converter.YamlContractConverter
import org.springframework.cloud.contract.verifier.file.SingleContractMetadata
import org.springframework.cloud.contract.verifier.util.ContentType
import org.springframework.cloud.contract.verifier.util.MapConverter
@@ -95,6 +94,47 @@ class WireMockResponseStubStrategySpec extends Specification {
assert body.get("double") instanceof BigDecimal
}
@Issue("#1656")
def "should not quote numbers, booleans, and null inside arrays"() {
given:
def irrelevantStatus = 200
def contract = Contract.make {
request {
method GET()
url "/foo"
}
response {
status irrelevantStatus
body([
anyPositiveInt(),
anyInteger(),
true,
anyNumber(),
null,
"value"
])
}
}
when:
SingleContractMetadata metadata = Stub()
metadata.evaluatedOutputStubContentType >> ContentType.JSON
def subject = new WireMockResponseStubStrategy(contract, metadata) {
@Override
Function parsingClosureForContentType() {
return MapConverter.JSON_PARSING_FUNCTION
}
}
def content = subject.buildClientResponseContent()
then:
List body = new JsonSlurper().parseText(content.body) as List
assert body.getAt(0) instanceof Integer
assert body.getAt(1) instanceof Integer
assert body.getAt(2) instanceof Boolean
assert body.getAt(3) instanceof Number
assert body.getAt(4) == null
assert body.getAt(5) instanceof String
}
def "should convert patterns to proper value"() {
given:
def contract = Contract.make {