Made all the cases work apart from method execution and mulitparts. Added tests for JUnit.

This commit is contained in:
Olga Maciaszek-Sharma
2016-02-19 15:55:08 +01:00
parent cdb7a088c5
commit 210b9f0bff
9 changed files with 1134 additions and 96 deletions

View File

@@ -62,6 +62,17 @@ class BlockBuilder {
return this
}
BlockBuilder addAtTheEnd(String toAdd) {
if (builder.charAt(builder.length() - 1) as String == '\n') {
builder.replace(builder.length() - 1, builder.length(), toAdd)
builder << '\n'
} else {
builder << toAdd
}
return this
}
@Override
String toString() {
return builder.toString()

View File

@@ -5,6 +5,8 @@ import groovy.transform.PackageScope
import groovy.transform.TypeChecked
import io.codearte.accurest.dsl.GroovyDsl
import io.codearte.accurest.dsl.internal.ExecutionProperty
import io.codearte.accurest.dsl.internal.Header
import io.codearte.accurest.dsl.internal.Request
/**
* @author Jakub Kubrynski
@@ -18,14 +20,9 @@ abstract class JUnitMethodBodyBuilder extends MethodBodyBuilder {
super(stubDefinition)
}
@Override
protected void when(BlockBuilder bb) {
}
@Override
protected String getResponseAsString() {
return null
return "response.getBody().asString()"
}
@Override
@@ -34,8 +31,9 @@ abstract class JUnitMethodBodyBuilder extends MethodBodyBuilder {
}
@Override
protected String addColonIfRequired(String baseString) {
return "$baseString;"
protected BlockBuilder addColonIfRequired(BlockBuilder blockBuilder) {
blockBuilder.addAtTheEnd(';')
return blockBuilder
}
@Override
@@ -60,7 +58,8 @@ abstract class JUnitMethodBodyBuilder extends MethodBodyBuilder {
@Override
protected String convertUnicodeEscapesIfRequired(String json) {
return json // TODO: verify if that's fine or escapeJava required
String unescapedJson = StringEscapeUtils.unescapeJavaScript(json)
return StringEscapeUtils.escapeJava(unescapedJson)
}
@Override
@@ -77,4 +76,24 @@ abstract class JUnitMethodBodyBuilder extends MethodBodyBuilder {
protected String getSimpleResponseBodyString(String responseString) {
return "Object responseBody = ($responseString);"
}
@Override
protected String getResponseString(Request request) {
return 'ResponseOptions response = given().spec(request)'
}
@Override
protected String getRequestString() {
return 'MockMvcRequestSpecification request = given()'
}
@Override
protected String getHeaderString(Header header) {
return ".header(\"${getTestSideValue(header.name)}\", \"${getTestSideValue(header.serverValue)}\")"
}
@Override
protected String getBodyString(String bodyAsString) {
return ".body(\"$bodyAsString\")"
}
}

View File

@@ -1,4 +1,5 @@
package io.codearte.accurest.builder
import groovy.transform.PackageScope
import groovy.transform.TypeChecked
import io.codearte.accurest.dsl.GroovyDsl
@@ -14,6 +15,9 @@ class JaxRsClientSpockMethodBodyBuilder extends SpockMethodBodyBuilder {
super(stubDefinition)
}
@Override
protected void given(BlockBuilder bb) {}
@Override
protected void givenBlock(BlockBuilder bb) {
}

View File

@@ -3,13 +3,16 @@ package io.codearte.accurest.builder
import groovy.json.JsonOutput
import groovy.transform.PackageScope
import groovy.transform.TypeChecked
import groovy.transform.TypeCheckingMode
import io.codearte.accurest.dsl.GroovyDsl
import io.codearte.accurest.dsl.internal.DslProperty
import io.codearte.accurest.dsl.internal.ExecutionProperty
import io.codearte.accurest.dsl.internal.Header
import io.codearte.accurest.dsl.internal.MatchingStrategy
import io.codearte.accurest.dsl.internal.QueryParameter
import io.codearte.accurest.dsl.internal.Request
import io.codearte.accurest.dsl.internal.Response
import io.codearte.accurest.dsl.internal.Url
import io.codearte.accurest.util.ContentType
import io.codearte.accurest.util.JsonPaths
import io.codearte.accurest.util.JsonToJsonPathsConverter
@@ -39,15 +42,11 @@ abstract class MethodBodyBuilder {
protected abstract void validateResponseHeadersBlock(BlockBuilder bb)
protected void given(BlockBuilder bb) {}
protected abstract void when(BlockBuilder bb)
protected abstract String getResponseAsString()
protected abstract String addCommentSignIfRequired(String baseString)
protected abstract String addColonIfRequired(String baseString)
protected abstract BlockBuilder addColonIfRequired(BlockBuilder blockBuilder)
protected abstract String getResponseBodyPropertyComparisonString(String property, String value)
@@ -65,6 +64,14 @@ abstract class MethodBodyBuilder {
protected abstract String getSimpleResponseBodyString(String responseString)
protected abstract String getResponseString(Request request)
protected abstract String getRequestString()
protected abstract String getHeaderString(Header header)
protected abstract String getBodyString(String bodyAsString)
void appendTo(BlockBuilder blockBuilder) {
blockBuilder.startBlock()
@@ -74,6 +81,7 @@ abstract class MethodBodyBuilder {
blockBuilder.endBlock()
}
protected void thenBlock(BlockBuilder bb) {
bb.addLine(addCommentSignIfRequired('then:'))
bb.startBlock()
@@ -95,6 +103,32 @@ abstract class MethodBodyBuilder {
bb.endBlock().addEmptyLine()
}
protected void given(BlockBuilder bb) {
bb.addLine(getRequestString())
bb.indent()
request.headers?.collect { Header header ->
bb.addLine(getHeaderString(header))
}
if (request.body) {
bb.addLine(getBodyString(bodyAsString))
}
if (request.multipart) {
multipartParameters?.each { Map.Entry<String, Object> entry -> bb.addLine(getMultipartParameterLine(entry)) }
}
addColonIfRequired(bb)
bb.unindent()
}
protected void when(BlockBuilder bb) {
bb.addLine(getResponseString(request))
bb.indent()
String url = buildUrl(request)
String method = request.method.serverValue.toString().toLowerCase()
bb.addLine(/.${method}("$url");/)
bb.unindent()
}
protected void then(BlockBuilder bb) {
validateResponseCodeBlock(bb)
@@ -103,7 +137,7 @@ abstract class MethodBodyBuilder {
}
if (response.body) {
bb.endBlock()
bb.addLine('and:').startBlock()
bb.addLine(addCommentSignIfRequired('and:')).startBlock()
validateResponseBodyBlock(bb)
}
}
@@ -115,18 +149,21 @@ abstract class MethodBodyBuilder {
responseBody = extractValue(responseBody, contentType, { DslProperty dslProperty -> dslProperty.serverValue })
}
if (contentType == ContentType.JSON) {
appendJsonPath(bb, responseAsString)
appendJsonPath(bb, getResponseAsString())
JsonPaths jsonPaths = JsonToJsonPathsConverter.transformToJsonPathWithTestsSideValues(responseBody)
jsonPaths.each {
bb.addLine("assertThat(parsedJson)" + it.method())
addColonIfRequired(bb)
}
processBodyElement(bb, "", responseBody)
} else if (contentType == ContentType.XML) {
bb.addLine(getParsedXmlResponseBodyString(responseAsString))
bb.addLine(getParsedXmlResponseBodyString(getResponseAsString()))
addColonIfRequired(bb)
// TODO xml validation
} else {
bb.addLine(getSimpleResponseBodyString(responseAsString))
} else {
bb.addLine(getSimpleResponseBodyString(getResponseAsString()))
processText(bb, "", responseBody as String)
addColonIfRequired(bb)
}
}
@@ -139,15 +176,18 @@ abstract class MethodBodyBuilder {
}
protected void appendJsonPath(BlockBuilder blockBuilder, String json) {
blockBuilder.addLine(addColonIfRequired("DocumentContext parsedJson = JsonPath.parse($json)"))
blockBuilder.addLine(("DocumentContext parsedJson = JsonPath.parse($json)"))
addColonIfRequired(blockBuilder)
}
protected void processText(BlockBuilder blockBuilder, String property, String value) {
if (value.startsWith('$')) {
value = value.substring(1).replaceAll('\\$value', "responseBody$property")
blockBuilder.addLine(value)
addColonIfRequired(blockBuilder)
} else {
blockBuilder.addLine(getResponseBodyPropertyComparisonString(property, value))
addColonIfRequired(blockBuilder)
}
}
@@ -226,4 +266,32 @@ abstract class MethodBodyBuilder {
processBodyElement(blockBuilder, prop, listElement)
}
}
protected String buildUrl(Request request) {
if (request.url)
return getTestSideValue(buildUrlFromUrlPath(request.url))
if (request.urlPath)
return getTestSideValue(buildUrlFromUrlPath(request.urlPath))
throw new IllegalStateException("URL is not set!")
}
@TypeChecked(TypeCheckingMode.SKIP)
protected String buildUrlFromUrlPath(Url url) {
if (hasQueryParams(url)) {
String params = url.queryParameters.parameters
.findAll(this.&allowedQueryParameter)
.inject([] as List<String>) { List<String> result, QueryParameter param ->
result << "${param.name}=${resolveParamValue(param).toString()}"
}
.join('&')
return "${MapConverter.getTestSideValues(url.serverValue)}?$params"
}
return MapConverter.getTestSideValues(url.serverValue)
}
private boolean hasQueryParams(Url url) {
return url.queryParameters
}
}

View File

@@ -9,7 +9,7 @@ import java.util.regex.Pattern
* @author Olga Maciaszek-Sharma
* @since 2016-02-17
*/
class MockMvcJUnitMethodBodyBuilder extends JUnitMethodBodyBuilder{
class MockMvcJUnitMethodBodyBuilder extends JUnitMethodBodyBuilder {
MockMvcJUnitMethodBodyBuilder(GroovyDsl stubDefinition) {
super(stubDefinition)
@@ -28,10 +28,12 @@ class MockMvcJUnitMethodBodyBuilder extends JUnitMethodBodyBuilder{
}
private String createHeaderComparison(Object headerValue) {
return "isEqualTo(\"$headerValue\");"
String escapedHeader = convertUnicodeEscapesIfRequired("$headerValue")
return "isEqualTo(\"$escapedHeader\");"
}
private String createHeaderComparison(Pattern headerValue) {
return "matches(\"$headerValue\");"
String escapedHeader = convertUnicodeEscapesIfRequired("$headerValue")
return "matches(\"$escapedHeader\");"
}
}

View File

@@ -2,13 +2,8 @@ package io.codearte.accurest.builder
import groovy.transform.PackageScope
import groovy.transform.TypeChecked
import groovy.transform.TypeCheckingMode
import io.codearte.accurest.dsl.GroovyDsl
import io.codearte.accurest.dsl.internal.Header
import io.codearte.accurest.dsl.internal.QueryParameter
import io.codearte.accurest.dsl.internal.Request
import io.codearte.accurest.dsl.internal.Url
import io.codearte.accurest.util.MapConverter
import java.util.regex.Pattern
@@ -20,36 +15,12 @@ class MockMvcSpockMethodBodyBuilder extends SpockMethodBodyBuilder {
super(stubDefinition)
}
protected void given(BlockBuilder bb) {
bb.addLine('def request = given()')
bb.indent()
request.headers?.collect { Header header ->
bb.addLine(".header('${getTestSideValue(header.name)}', '${getTestSideValue(header.serverValue)}')")
}
if (request.body) {
bb.addLine(".body('''$bodyAsString''')")
}
if (request.multipart) {
multipartParameters?.each { Map.Entry<String, Object> entry -> bb.addLine(getMultipartParameterLine(entry)) }
}
bb.unindent()
}
protected void when(BlockBuilder bb) {
bb.addLine('def response = given().spec(request)')
bb.indent()
String url = buildUrl(request)
String method = request.method.serverValue.toString().toLowerCase()
bb.addLine(/.${method}("$url")/)
bb.unindent()
}
@Override
protected void validateResponseCodeBlock(BlockBuilder bb) {
bb.addLine("response.statusCode == $response.status.serverValue")
}
@Override
protected void validateResponseHeadersBlock(BlockBuilder bb) {
response.headers?.collect { Header header ->
bb.addLine("response.header('$header.name') ${convertHeaderComparison(header.serverValue)}")
@@ -68,30 +39,4 @@ class MockMvcSpockMethodBodyBuilder extends SpockMethodBodyBuilder {
protected String getResponseAsString() {
return 'response.body.asString()'
}
protected String buildUrl(Request request) {
if (request.url)
return getTestSideValue(buildUrlFromUrlPath(request.url))
if (request.urlPath)
return getTestSideValue(buildUrlFromUrlPath(request.urlPath))
throw new IllegalStateException("URL is not set!")
}
@TypeChecked(TypeCheckingMode.SKIP)
protected String buildUrlFromUrlPath(Url url) {
if (hasQueryParams(url)) {
String params = url.queryParameters.parameters
.findAll(this.&allowedQueryParameter)
.inject([] as List<String>) { List<String> result, QueryParameter param ->
result << "${param.name}=${resolveParamValue(param).toString()}"
}
.join('&')
return "${MapConverter.getTestSideValues(url.serverValue)}?$params"
}
return MapConverter.getTestSideValues(url.serverValue)
}
private boolean hasQueryParams(Url url) {
return url.queryParameters
}
}

View File

@@ -1,22 +1,15 @@
package io.codearte.accurest.builder
import groovy.json.JsonOutput
import groovy.json.StringEscapeUtils
import groovy.transform.PackageScope
import groovy.transform.TypeChecked
import io.codearte.accurest.dsl.GroovyDsl
import io.codearte.accurest.dsl.internal.DslProperty
import io.codearte.accurest.dsl.internal.ExecutionProperty
import io.codearte.accurest.dsl.internal.MatchingStrategy
import io.codearte.accurest.dsl.internal.Header
import io.codearte.accurest.dsl.internal.NamedProperty
import io.codearte.accurest.dsl.internal.QueryParameter
import io.codearte.accurest.util.ContentType
import io.codearte.accurest.util.MapConverter
import io.codearte.accurest.dsl.internal.Request
import static io.codearte.accurest.util.ContentUtils.extractValue
import static io.codearte.accurest.util.ContentUtils.getMultipartFileParameterContent
import static io.codearte.accurest.util.ContentUtils.recognizeContentTypeFromContent
import static io.codearte.accurest.util.ContentUtils.recognizeContentTypeFromHeader
/**
* @author Jakub Kubrynski
@@ -58,8 +51,8 @@ abstract class SpockMethodBodyBuilder extends MethodBodyBuilder {
}
@Override
protected String addColonIfRequired(String baseString) {
return baseString
protected BlockBuilder addColonIfRequired(BlockBuilder blockBuilder) {
return blockBuilder
}
@Override
@@ -74,11 +67,32 @@ abstract class SpockMethodBodyBuilder extends MethodBodyBuilder {
@Override
protected String getParsedXmlResponseBodyString(String responseString) {
return "def responseBody = new XmlSlurper().parseText($responseAsString)"
return "def responseBody = new XmlSlurper().parseText($responseString)"
}
@Override
protected String getSimpleResponseBodyString(String responseString) {
return "def responseBody = ($responseAsString)"
return "def responseBody = ($responseString)"
}
@Override
protected String getResponseString(Request request) {
return 'def response = given().spec(request)'
}
@Override
protected String getRequestString() {
return 'def request = given()'
}
@Override
protected String getHeaderString(Header header) {
return ".header('${getTestSideValue(header.name)}', '${getTestSideValue(header.serverValue)}')"
}
@Override
protected String getBodyString(String bodyAsString) {
return ".body('''$bodyAsString''')"
}
}

View File

@@ -2,6 +2,8 @@ package io.codearte.accurest.util;
import com.blogspot.toomuchcoding.jsonassert.JsonVerifiable;
import static org.apache.commons.lang3.StringEscapeUtils.escapeJava;
/**
* @author Marcin Grzejszczak
*/
@@ -11,7 +13,7 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable {
private final StringBuffer methodsBuffer;
DelegatingJsonVerifiable(JsonVerifiable delegate,
StringBuffer methodsBuffer) {
StringBuffer methodsBuffer) {
this.delegate = delegate;
this.methodsBuffer = new StringBuffer(methodsBuffer.toString());
}
@@ -100,7 +102,7 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable {
if (delegate.isAssertingAValueInArray()) {
readyToCheck.methodsBuffer.append(".value()");
} else {
readyToCheck.appendMethodWithQuotedValue("isEqualTo", value);
readyToCheck.appendMethodWithQuotedValue("isEqualTo", escapeJava(value));
}
return readyToCheck;
}
@@ -137,7 +139,7 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable {
if (delegate.isAssertingAValueInArray()) {
readyToCheck.methodsBuffer.append(".value()");
} else {
readyToCheck.appendMethodWithQuotedValue("matches", value);
readyToCheck.appendMethodWithQuotedValue("matches", escapeJava(value));
}
return readyToCheck;
}

View File

@@ -0,0 +1,973 @@
package io.codearte.accurest.builder
import io.codearte.accurest.dsl.GroovyDsl
import io.codearte.accurest.dsl.WireMockStubStrategy
import io.codearte.accurest.dsl.WireMockStubVerifier
import io.codearte.accurest.file.Contract
import jdk.nashorn.internal.ir.annotations.Ignore
import spock.lang.Issue
import spock.lang.Specification
import spock.lang.Unroll
import java.util.regex.Pattern
/**
* @author Olga Maciaszek-Sharma
* @since 2015-08-07
*/
class MockMvcJunitMethodBuilderSpec extends Specification implements WireMockStubVerifier {
def "should generate assertions for simple response body"() {
given:
GroovyDsl contractDsl = GroovyDsl.make {
request {
method "GET"
url "test"
}
response {
status 200
body """{
"property1": "a",
"property2": "b"
}"""
}
}
MockMvcJUnitMethodBodyBuilder builder = new MockMvcJUnitMethodBodyBuilder(contractDsl)
BlockBuilder blockBuilder = new BlockBuilder(" ")
when:
builder.appendTo(blockBuilder)
then:
blockBuilder.toString().contains('assertThat(parsedJson).field("property1").isEqualTo("a");')
blockBuilder.toString().contains('assertThat(parsedJson).field("property2").isEqualTo("b");')
and:
stubMappingIsValidWireMockStub(new WireMockStubStrategy("Test", new Contract(null, false, 0, null), contractDsl).toWireMockClientStub())
}
@Issue("#187")
def "should generate assertions for null and boolean values"() {
given:
GroovyDsl contractDsl = GroovyDsl.make {
request {
method "GET"
url "test"
}
response {
status 200
body """{
"property1": "true",
"property2": null,
"property3": false
}"""
}
}
MockMvcJUnitMethodBodyBuilder builder = new MockMvcJUnitMethodBodyBuilder(contractDsl)
BlockBuilder blockBuilder = new BlockBuilder(" ")
when:
builder.appendTo(blockBuilder)
then:
blockBuilder.toString().contains("""assertThat(parsedJson).field("property1").isEqualTo("true");""")
blockBuilder.toString().contains("""assertThat(parsedJson).field("property2").isNull();""")
blockBuilder.toString().contains("""assertThat(parsedJson).field("property3").isEqualTo(false);""")
and:
stubMappingIsValidWireMockStub(new WireMockStubStrategy("Test", new Contract(null, false, 0, null), contractDsl).toWireMockClientStub())
}
@Issue("#79")
def "should generate assertions for simple response body constructed from map with a list"() {
given:
GroovyDsl contractDsl = GroovyDsl.make {
request {
method "GET"
url "test"
}
response {
status 200
body(
property1: 'a',
property2: [
[a: 'sth'],
[b: 'sthElse']
]
)
}
}
MockMvcJUnitMethodBodyBuilder builder = new MockMvcJUnitMethodBodyBuilder(contractDsl)
BlockBuilder blockBuilder = new BlockBuilder(" ")
when:
builder.appendTo(blockBuilder)
then:
blockBuilder.toString().contains("""assertThat(parsedJson).field("property1").isEqualTo("a");""")
blockBuilder.toString().contains("""assertThat(parsedJson).array("property2").contains("a").isEqualTo("sth");""")
blockBuilder.toString().contains("""assertThat(parsedJson).array("property2").contains("b").isEqualTo("sthElse");""")
and:
stubMappingIsValidWireMockStub(new WireMockStubStrategy("Test", new Contract(null, false, 0, null), contractDsl).toWireMockClientStub())
}
@Issue("#82")
def "should generate proper request when body constructed from map with a list"() {
given:
GroovyDsl contractDsl = GroovyDsl.make {
request {
method "GET"
url "test"
body(
items: ['HOP']
)
}
response {
status 200
}
}
MockMvcJUnitMethodBodyBuilder builder = new MockMvcJUnitMethodBodyBuilder(contractDsl)
BlockBuilder blockBuilder = new BlockBuilder(" ")
when:
builder.appendTo(blockBuilder)
then:
blockBuilder.toString().contains('.body("{\\"items\\":[\\"HOP\\"]}")')
and:
stubMappingIsValidWireMockStub(new WireMockStubStrategy("Test", new Contract(null, false, 0, null), contractDsl).toWireMockClientStub())
}
@Issue("#88")
def "should generate proper request when body constructed from GString"() {
given:
GroovyDsl contractDsl = GroovyDsl.make {
request {
method "GET"
url "test"
body(
"property1=VAL1"
)
}
response {
status 200
}
}
MockMvcJUnitMethodBodyBuilder builder = new MockMvcJUnitMethodBodyBuilder(contractDsl)
BlockBuilder blockBuilder = new BlockBuilder(" ")
when:
builder.appendTo(blockBuilder)
then:
blockBuilder.toString().contains('.body("\\"property1=VAL1\\"")')
and:
stubMappingIsValidWireMockStub(new WireMockStubStrategy("Test", new Contract(null, false, 0, null), contractDsl).toWireMockClientStub())
}
@Issue("185")
def "should generate assertions for a response body containing map with integers as keys"() {
given:
GroovyDsl contractDsl = GroovyDsl.make {
request {
method "GET"
url "test"
}
response {
status 200
body(
property: [
14: 0.0,
7 : 0.0
]
)
}
}
MockMvcJUnitMethodBodyBuilder builder = new MockMvcJUnitMethodBodyBuilder(contractDsl)
BlockBuilder blockBuilder = new BlockBuilder(" ")
when:
builder.appendTo(blockBuilder)
then:
blockBuilder.toString().contains("""assertThat(parsedJson).field("property").field(7).isEqualTo(0.0);""")
blockBuilder.toString().contains("""assertThat(parsedJson).field("property").field(14).isEqualTo(0.0);""")
and:
stubMappingIsValidWireMockStub(new WireMockStubStrategy("Test", new Contract(null, false, 0, null), contractDsl).toWireMockClientStub())
}
def "should generate assertions for array in response body"() {
given:
GroovyDsl contractDsl = GroovyDsl.make {
request {
method "GET"
url "test"
}
response {
status 200
body """[
{
"property1": "a"
},
{
"property2": "b"
}]"""
}
}
MockMvcJUnitMethodBodyBuilder builder = new MockMvcJUnitMethodBodyBuilder(contractDsl)
BlockBuilder blockBuilder = new BlockBuilder(" ")
when:
builder.appendTo(blockBuilder)
then:
blockBuilder.toString().contains("""assertThat(parsedJson).array().contains("property2").isEqualTo("b");""")
blockBuilder.toString().contains("""assertThat(parsedJson).array().contains("property1").isEqualTo("a");""")
and:
stubMappingIsValidWireMockStub(new WireMockStubStrategy("Test", new Contract(null, false, 0, null), contractDsl).toWireMockClientStub())
}
def "should generate assertions for array inside response body element"() {
given:
GroovyDsl contractDsl = GroovyDsl.make {
request {
method "GET"
url "test"
}
response {
status 200
body """{
"property1": [
{ "property2": "test1"},
{ "property3": "test2"}
]
}"""
}
}
MockMvcJUnitMethodBodyBuilder builder = new MockMvcJUnitMethodBodyBuilder(contractDsl)
BlockBuilder blockBuilder = new BlockBuilder(" ")
when:
builder.appendTo(blockBuilder)
then:
blockBuilder.toString().contains("""assertThat(parsedJson).array("property1").contains("property2").isEqualTo("test1");""")
blockBuilder.toString().contains("""assertThat(parsedJson).array("property1").contains("property3").isEqualTo("test2");""")
and:
stubMappingIsValidWireMockStub(new WireMockStubStrategy("Test", new Contract(null, false, 0, null), contractDsl).toWireMockClientStub())
}
def "should generate assertions for nested objects in response body"() {
given:
GroovyDsl contractDsl = GroovyDsl.make {
request {
method "GET"
url "test"
}
response {
status 200
body '''\
{
"property1": "a",
"property2": {"property3": "b"}
}
'''
}
}
MockMvcJUnitMethodBodyBuilder builder = new MockMvcJUnitMethodBodyBuilder(contractDsl)
BlockBuilder blockBuilder = new BlockBuilder(" ")
when:
builder.appendTo(blockBuilder)
then:
blockBuilder.toString().contains("""assertThat(parsedJson).field("property2").field("property3").isEqualTo("b");""")
blockBuilder.toString().contains("""assertThat(parsedJson).field("property1").isEqualTo("a");""")
and:
stubMappingIsValidWireMockStub(new WireMockStubStrategy("Test", new Contract(null, false, 0, null), contractDsl).toWireMockClientStub())
}
def "should generate regex assertions for map objects in response body"() {
given:
GroovyDsl contractDsl = GroovyDsl.make {
request {
method "GET"
url "test"
}
response {
status 200
body(
property1: "a",
property2: value(
client('123'),
server(regex('[0-9]{3}'))
)
)
headers {
header('Content-Type': 'application/json')
}
}
}
MockMvcJUnitMethodBodyBuilder builder = new MockMvcJUnitMethodBodyBuilder(contractDsl)
BlockBuilder blockBuilder = new BlockBuilder(" ")
when:
builder.appendTo(blockBuilder)
then:
blockBuilder.toString().contains("""assertThat(parsedJson).field("property2").matches("[0-9]{3}");""")
blockBuilder.toString().contains("""assertThat(parsedJson).field("property1").isEqualTo("a");""")
and:
stubMappingIsValidWireMockStub(new WireMockStubStrategy("Test", new Contract(null, false, 0, null), contractDsl).toWireMockClientStub())
}
def "should generate regex assertions for string objects in response body"() {
given:
GroovyDsl contractDsl = GroovyDsl.make {
request {
method "GET"
url "test"
}
response {
status 200
body("""{"property1":"a","property2":"${value(client('123'), server(regex('[0-9]{3}')))}"}""")
headers {
header('Content-Type': 'application/json')
}
}
}
MockMvcJUnitMethodBodyBuilder builder = new MockMvcJUnitMethodBodyBuilder(contractDsl)
BlockBuilder blockBuilder = new BlockBuilder(" ")
when:
builder.appendTo(blockBuilder)
then:
blockBuilder.toString().contains("""assertThat(parsedJson).field("property2").matches("[0-9]{3}");""")
blockBuilder.toString().contains("""assertThat(parsedJson).field("property1").isEqualTo("a");""")
and:
stubMappingIsValidWireMockStub(new WireMockStubStrategy("Test", new Contract(null, false, 0, null), contractDsl).toWireMockClientStub())
}
@Issue(["#126", "#143"])
def "should generate escaped regex assertions for string objects in response body"() {
given:
GroovyDsl contractDsl = GroovyDsl.make {
request {
method "GET"
url "test"
}
response {
status 200
body("""{"property":" ${value(client('123'), server(regex('\\d+')))}"}""")
headers {
header('Content-Type': 'application/json')
}
}
}
MockMvcJUnitMethodBodyBuilder builder = new MockMvcJUnitMethodBodyBuilder(contractDsl)
BlockBuilder blockBuilder = new BlockBuilder(" ")
when:
builder.appendTo(blockBuilder)
then:
blockBuilder.toString().contains("""assertThat(parsedJson).field("property").matches("\\\\d+");""")
and:
stubMappingIsValidWireMockStub(new WireMockStubStrategy("Test", new Contract(null, false, 0, null), contractDsl).toWireMockClientStub())
}
def "should generate a call with an url path and query parameters"() {
given:
GroovyDsl contractDsl = GroovyDsl.make {
request {
method 'GET'
urlPath('/users') {
queryParameters {
parameter 'limit': $(client(equalTo("20")), server(equalTo("10")))
parameter 'offset': $(client(containing("20")), server(equalTo("20")))
parameter 'filter': "email"
parameter 'sort': equalTo("name")
parameter 'search': $(client(notMatching(~/^\/[0-9]{2}$/)), server("55"))
parameter 'age': $(client(notMatching("^\\w*\$")), server("99"))
parameter 'name': $(client(matching("Denis.*")), server("Denis.Stepanov"))
parameter 'email': "bob@email.com"
parameter 'hello': $(client(matching("Denis.*")), server(absent()))
parameter 'hello': absent()
}
}
}
response {
status 200
body """
{
"property1": "a",
"property2": "b"
}
"""
}
}
MockMvcJUnitMethodBodyBuilder builder = new MockMvcJUnitMethodBodyBuilder(contractDsl)
BlockBuilder blockBuilder = new BlockBuilder(" ")
when:
builder.appendTo(blockBuilder)
def jUnitTest = blockBuilder.toString()
then:
jUnitTest.contains('get("/users?limit=10&offset=20&filter=email&sort=name&search=55&age=99&name=Denis.Stepanov&email=bob@email.com")')
jUnitTest.contains('assertThat(parsedJson).field("property1").isEqualTo("a")')
jUnitTest.contains('assertThat(parsedJson).field("property2").isEqualTo("b")')
and:
stubMappingIsValidWireMockStub(new WireMockStubStrategy("Test", new Contract(null, false, 0, null), contractDsl).toWireMockClientStub())
}
@Issue('#169')
def "should generate a call with an url path and query parameters with url containing a pattern"() {
given:
GroovyDsl contractDsl = GroovyDsl.make {
request {
method 'GET'
url($(stub(regex('/foo/[0-9]+')), test('/foo/123456'))) {
queryParameters {
parameter 'limit': $(client(equalTo("20")), server(equalTo("10")))
parameter 'offset': $(client(containing("20")), server(equalTo("20")))
parameter 'filter': "email"
parameter 'sort': equalTo("name")
parameter 'search': $(client(notMatching(~/^\/[0-9]{2}$/)), server("55"))
parameter 'age': $(client(notMatching("^\\w*\$")), server("99"))
parameter 'name': $(client(matching("Denis.*")), server("Denis.Stepanov"))
parameter 'email': "bob@email.com"
parameter 'hello': $(client(matching("Denis.*")), server(absent()))
parameter 'hello': absent()
}
}
}
response {
status 200
body """
{
"property1": "a",
"property2": "b"
}
"""
}
}
MockMvcJUnitMethodBodyBuilder builder = new MockMvcJUnitMethodBodyBuilder(contractDsl)
BlockBuilder blockBuilder = new BlockBuilder(" ")
when:
builder.appendTo(blockBuilder)
def jUnitTest = blockBuilder.toString()
then:
jUnitTest.contains('get("/foo/123456?limit=10&offset=20&filter=email&sort=name&search=55&age=99&name=Denis.Stepanov&email=bob@email.com")')
jUnitTest.contains('assertThat(parsedJson).field("property1").isEqualTo("a")')
jUnitTest.contains('assertThat(parsedJson).field("property2").isEqualTo("b")')
and:
stubMappingIsValidWireMockStub(new WireMockStubStrategy("Test", new Contract(null, false, 0, null), contractDsl).toWireMockClientStub())
}
def "should generate test for empty body"() {
given:
GroovyDsl contractDsl = GroovyDsl.make {
request {
method('POST')
url("/ws/payments")
body("")
}
response {
status 406
}
}
MockMvcJUnitMethodBodyBuilder builder = new MockMvcJUnitMethodBodyBuilder(contractDsl)
BlockBuilder blockBuilder = new BlockBuilder(" ")
when:
builder.appendTo(blockBuilder)
def jUnitTest = blockBuilder.toString()
then:
jUnitTest.contains(".body(\"\\\"\\\"\")")
and:
stubMappingIsValidWireMockStub(new WireMockStubStrategy("Test", new Contract(null, false, 0, null), contractDsl).toWireMockClientStub())
}
def "should generate test for String in response body"() {
given:
GroovyDsl contractDsl = GroovyDsl.make {
request {
method "POST"
url "test"
}
response {
status 200
body "test"
}
}
MockMvcJUnitMethodBodyBuilder builder = new MockMvcJUnitMethodBodyBuilder(contractDsl)
BlockBuilder blockBuilder = new BlockBuilder(" ")
when:
builder.appendTo(blockBuilder)
def jUnitTest = blockBuilder.toString()
then:
jUnitTest.contains('Object responseBody = (response.getBody().asString());')
jUnitTest.contains('assertThat(responseBody).isEqualTo("test");')
and:
stubMappingIsValidWireMockStub(new WireMockStubStrategy("Test", new Contract(null, false, 0, null), contractDsl).toWireMockClientStub())
}
@Issue('113')
def "should generate regex test for String in response header"() {
given:
GroovyDsl contractDsl = GroovyDsl.make {
request {
method 'POST'
url $(client(regex('/partners/[0-9]+/users')), server('/partners/1000/users'))
headers { header 'Content-Type': 'application/json' }
body(
first_name: 'John',
last_name: 'Smith',
personal_id: '12345678901',
phone_number: '500500500',
invitation_token: '00fec7141bb94793bfe7ae1d0f39bda0',
password: 'john'
)
}
response {
status 201
headers {
header 'Location': $(client('http://localhost/partners/1000/users/1001'), server(regex('http://localhost/partners/[0-9]+/users/[0-9]+')))
}
}
}
MockMvcJUnitMethodBodyBuilder builder = new MockMvcJUnitMethodBodyBuilder(contractDsl)
BlockBuilder blockBuilder = new BlockBuilder(" ")
when:
builder.appendTo(blockBuilder)
def jUnitTest = blockBuilder.toString()
then:
jUnitTest.contains('assertThat(response.header("Location")).matches("http://localhost/partners/[0-9]+/users/[0-9]+");')
and:
stubMappingIsValidWireMockStub(new WireMockStubStrategy("Test", new Contract(null, false, 0, null), contractDsl).toWireMockClientStub())
}
@Issue('115')
def "should generate regex with helper method"() {
given:
GroovyDsl contractDsl = GroovyDsl.make {
request {
method 'POST'
url $(client(regex('/partners/[0-9]+/users')), server('/partners/1000/users'))
headers { header 'Content-Type': 'application/json' }
body(
first_name: 'John',
last_name: 'Smith',
personal_id: '12345678901',
phone_number: '500500500',
invitation_token: '00fec7141bb94793bfe7ae1d0f39bda0',
password: 'john'
)
}
response {
status 201
headers {
header 'Location': $(client('http://localhost/partners/1000/users/1001'), server(regex("^${hostname()}/partners/[0-9]+/users/[0-9]+")))
}
}
}
MockMvcJUnitMethodBodyBuilder builder = new MockMvcJUnitMethodBodyBuilder(contractDsl)
BlockBuilder blockBuilder = new BlockBuilder(" ")
when:
builder.appendTo(blockBuilder)
def jUnitTest = blockBuilder.toString()
then:
jUnitTest.contains('assertThat(response.header("Location")).matches("^((http[s]?|ftp):/)/?([^:/s]+)(:[0-9]{1,5})?/partners/[0-9]+/users/[0-9]+");')
and:
stubMappingIsValidWireMockStub(new WireMockStubStrategy("Test", new Contract(null, false, 0, null), contractDsl).toWireMockClientStub())
}
def "should work with more complex stuff and jsonpaths"() {
given:
GroovyDsl contractDsl = GroovyDsl.make {
priority 10
request {
method 'POST'
url '/validation/client'
headers {
header 'Content-Type': 'application/json'
}
body(
bank_account_number: '0014282912345698765432161182',
email: 'foo@bar.com',
phone_number: '100299300',
personal_id: 'ABC123456'
)
}
response {
status 200
body(errors: [
[property: "bank_account_number", message: "incorrect_format"]
])
}
}
MockMvcJUnitMethodBodyBuilder builder = new MockMvcJUnitMethodBodyBuilder(contractDsl)
BlockBuilder blockBuilder = new BlockBuilder(" ")
when:
builder.appendTo(blockBuilder)
def jUnitTest = blockBuilder.toString()
then:
jUnitTest.contains("""assertThat(parsedJson).array("errors").contains("property").isEqualTo("bank_account_number");""")
jUnitTest.contains("""assertThat(parsedJson).array("errors").contains("message").isEqualTo("incorrect_format");""")
and:
stubMappingIsValidWireMockStub(new WireMockStubStrategy("Test", new Contract(null, false, 0, null), contractDsl).toWireMockClientStub())
}
def "should work properly with GString url"() {
given:
GroovyDsl contractDsl = GroovyDsl.make {
request {
method 'PUT'
url "/partners/${value(client(regex('^[0-9]*$')), server('11'))}/agents/11/customers/09665703Z"
headers {
header 'Content-Type': 'application/json'
}
body(
first_name: 'Josef',
)
}
response {
status 422
}
}
MockMvcJUnitMethodBodyBuilder builder = new MockMvcJUnitMethodBodyBuilder(contractDsl)
BlockBuilder blockBuilder = new BlockBuilder(" ")
when:
builder.appendTo(blockBuilder)
def jUnitTest = blockBuilder.toString()
then:
jUnitTest.contains("/partners/11/agents/11/customers/09665703Z")
and:
stubMappingIsValidWireMockStub(new WireMockStubStrategy("Test", new Contract(null, false, 0, null), contractDsl).toWireMockClientStub())
}
def "should resolve properties in GString with regular expression"() {
given:
GroovyDsl contractDsl = GroovyDsl.make {
priority 1
request {
method 'POST'
url '/users/password'
headers {
header 'Content-Type': 'application/json'
}
body(
email: $(client(regex(email())), server('not.existing@user.com')),
callback_url: $(client(regex(hostname())), server('http://partners.com'))
)
}
response {
status 404
headers {
header 'Content-Type': 'application/json'
}
body(
code: 4,
message: "User not found by email = [${value(server(regex(email())), client('not.existing@user.com'))}]"
)
}
}
MockMvcJUnitMethodBodyBuilder builder = new MockMvcJUnitMethodBodyBuilder(contractDsl)
BlockBuilder blockBuilder = new BlockBuilder(" ")
when:
builder.appendTo(blockBuilder)
def jUnitTest = blockBuilder.toString()
then:
jUnitTest.contains('''$[?(@.message =~ /User not found by email = \\\\[[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\\\.[a-zA-Z]{2,4}\\\\]/)]''')
}
@Issue('42')
@Unroll
def "should not omit the optional field in the test creation"() {
given:
MockMvcJUnitMethodBodyBuilder builder = new MockMvcJUnitMethodBodyBuilder(contractDsl)
BlockBuilder blockBuilder = new BlockBuilder(" ")
when:
builder.appendTo(blockBuilder)
def jUnitTest = blockBuilder.toString()
then:
jUnitTest.contains('\\"email\\":\\"abc@abc.com\\"')
jUnitTest.contains('assertThat(parsedJson).field("code").matches("(123123)?");')
!jUnitTest.contains('''REGEXP''')
!jUnitTest.contains('''OPTIONAL''')
!jUnitTest.contains('''OptionalProperty''')
where:
contractDsl << [
GroovyDsl.make {
priority 1
request {
method 'POST'
url '/users/password'
headers {
header 'Content-Type': 'application/json'
}
body(
email: $(stub(optional(regex(email()))), test('abc@abc.com')),
callback_url: $(stub(regex(hostname())), test('http://partners.com'))
)
}
response {
status 404
headers {
header 'Content-Type': 'application/json'
}
body(
code: value(stub("123123"), test(optional("123123"))),
message: "User not found by email = [${value(test(regex(email())), stub('not.existing@user.com'))}]"
)
}
},
GroovyDsl.make {
priority 1
request {
method 'POST'
url '/users/password'
headers {
header 'Content-Type': 'application/json'
}
body(
""" {
"email" : "${value(stub(optional(regex(email()))), test('abc@abc.com'))}",
"callback_url" : "${value(client(regex(hostname())), server('http://partners.com'))}"
}
"""
)
}
response {
status 404
headers {
header 'Content-Type': 'application/json'
}
body(
""" {
"code" : "${value(stub(123123), test(optional(123123)))}",
"message" : "User not found by email = [${
value(server(regex(email())), client('not.existing@user.com'))
}]"
}
"""
)
}
}
]
}
@Issue('72')
@Ignore
//TODO: fix exec method for jUnit
def "should make the execute method work"() {
given:
GroovyDsl contractDsl = GroovyDsl.make {
request {
method """PUT"""
url """/fraudcheck"""
body("""
{
"clientPesel":"${value(client(regex('[0-9]{10}')), server('1234567890'))}",
"loanAmount":123.123
}
"""
)
headers {
header("""Content-Type""", """application/vnd.fraud.v1+json""")
}
}
response {
status 200
body("""{
"fraudCheckStatus": "OK",
"rejectionReason": ${value(client(null), server(execute('assertThatRejectionReasonIsNull($it)')))}
}""")
headers {
header('Content-Type': 'application/vnd.fraud.v1+json')
}
}
}
MockMvcJUnitMethodBodyBuilder builder = new MockMvcJUnitMethodBodyBuilder(contractDsl)
BlockBuilder blockBuilder = new BlockBuilder(" ")
when:
builder.appendTo(blockBuilder)
def jUnitTest = blockBuilder.toString()
then:
jUnitTest.contains('''assertThatRejectionReasonIsNull(parsedJson.read('$.rejectionReason'))''')
}
def "should support inner map and list definitions"() {
given:
Pattern PHONE_NUMBER = Pattern.compile(/[+\w]*/)
Pattern ANYSTRING = Pattern.compile(/.*/)
Pattern NUMBERS = Pattern.compile(/[\d\.]*/)
Pattern DATETIME = ANYSTRING
GroovyDsl contractDsl = GroovyDsl.make {
request {
method "PUT"
url "/v1/payments/e86df6f693de4b35ae648464c5b0dc09/client_data"
headers {
header('Content-Type': 'application/json')
}
body(
client: [
first_name : $(stub(regex(onlyAlphaUnicode())), test('Denis')),
last_name : $(stub(regex(onlyAlphaUnicode())), test('FakeName')),
email : $(stub(regex(email())), test('fakemail@fakegmail.com')),
fax : $(stub(PHONE_NUMBER), test('+xx001213214')),
phone : $(stub(PHONE_NUMBER), test('2223311')),
data_of_birth: $(stub(DATETIME), test('2002-10-22T00:00:00Z'))
],
client_id_card: [
id : $(stub(ANYSTRING), test('ABC12345')),
date_of_issue: $(stub(ANYSTRING), test('2002-10-02T00:00:00Z')),
address : [
street : $(stub(ANYSTRING), test('Light Street')),
city : $(stub(ANYSTRING), test('Fire')),
region : $(stub(ANYSTRING), test('Skys')),
country: $(stub(ANYSTRING), test('HG')),
zip : $(stub(NUMBERS), test('658965'))
]
],
incomes_and_expenses: [
monthly_income : $(stub(NUMBERS), test('0.0')),
monthly_loan_repayments: $(stub(NUMBERS), test('100')),
monthly_living_expenses: $(stub(NUMBERS), test('22'))
],
additional_info: [
allow_to_contact: $(stub(optional(regex(anyBoolean()))), test('true'))
]
)
}
response {
status 200
headers {
header('Content-Type': 'application/json')
}
}
}
MockMvcJUnitMethodBodyBuilder builder = new MockMvcJUnitMethodBodyBuilder(contractDsl)
BlockBuilder blockBuilder = new BlockBuilder(" ")
when:
builder.appendTo(blockBuilder)
def jUnitTest = blockBuilder.toString()
then:
jUnitTest.contains '\\"street\\":\\"Light Street\\"'
!jUnitTest.contains("clientValue")
!jUnitTest.contains("cursor")
}
def "shouldn't generate unicode escape characters"() {
given:
Pattern ONLY_ALPHA_UNICODE = Pattern.compile(/[\p{L}]*/)
GroovyDsl contractDsl = GroovyDsl.make {
request {
method "PUT"
url "/v1/payments/e86df6f693de4b35ae648464c5b0dc09/енев"
headers {
header('Content-Type': 'application/json')
}
body(
client: [
first_name: $(stub(ONLY_ALPHA_UNICODE), test('Пенева')),
last_name : $(stub(ONLY_ALPHA_UNICODE), test('Пенева'))
]
)
}
response {
status 200
headers {
header('Content-Type': 'application/json')
}
}
}
MockMvcJUnitMethodBodyBuilder builder = new MockMvcJUnitMethodBodyBuilder(contractDsl)
BlockBuilder blockBuilder = new BlockBuilder(" ")
when:
builder.appendTo(blockBuilder)
def jUnitTest = blockBuilder.toString()
then:
!jUnitTest.contains("\\u041f")
}
@Issue('177')
def "should generate proper test code when having multiline body"() {
given:
GroovyDsl contractDsl = GroovyDsl.make {
request {
method "PUT"
url "/multiline"
body('''hello,
World.''')
}
response {
status 200
}
}
MockMvcSpockMethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl)
BlockBuilder blockBuilder = new BlockBuilder(" ")
when:
builder.given(blockBuilder)
def spockTest = blockBuilder.toString()
then:
spockTest.contains("""'''hello,
World.'''""")
}
@Issue('180')
@Ignore
//TODO: fix multiparts in JUnit
def "should generate proper test code when having multipart parameters"() {
given:
GroovyDsl contractDsl = GroovyDsl.make {
request {
method "PUT"
url "/multipart"
headers {
header('content-type', 'multipart/form-data;boundary=AaB03x')
}
multipart(
formParameter: value(client(regex('.+')), server('"formParameterValue"')),
someBooleanParameter: value(client(regex('(true|false)')), server('true')),
file: named(value(client(regex('.+')), server('filename.csv')), value(client(regex('.+')), server('file content')))
)
}
response {
status 200
}
}
MockMvcJUnitMethodBodyBuilder builder = new MockMvcJUnitMethodBodyBuilder(contractDsl)
BlockBuilder blockBuilder = new BlockBuilder(" ")
when:
builder.given(blockBuilder)
def jUnitTest = blockBuilder.toString()
then:
jUnitTest.contains("""'content-type', 'multipart/form-data;boundary=AaB03x'""")
jUnitTest.contains(""".param('formParameter', '"formParameterValue"'""")
jUnitTest.contains(""".param('someBooleanParameter', 'true')""")
jUnitTest.contains(""".multiPart('file', 'filename.csv', 'file content'.bytes)""")
}
@Issue('180')
@Ignore
//TODO: fix multiparts in JUnit
def "should generate proper test code when having multipart parameters with named as map"() {
given:
GroovyDsl contractDsl = GroovyDsl.make {
request {
method "PUT"
url "/multipart"
multipart(
formParameter: value(client(regex('".+"')), server('"formParameterValue"')),
someBooleanParameter: value(client(regex('(true|false)')), server('true')),
file: named(
name: value(client(regex('.+')), server('filename.csv')),
content: value(client(regex('.+')), server('file content')))
)
}
response {
status 200
}
}
MockMvcJUnitMethodBodyBuilder builder = new MockMvcJUnitMethodBodyBuilder(contractDsl)
BlockBuilder blockBuilder = new BlockBuilder(" ")
when:
builder.given(blockBuilder)
def jUnitTest = blockBuilder.toString()
then:
jUnitTest.contains('.multiPart')
}
}