From 661c0dcbd72ba3acc34133e2409e4f3f452ed148 Mon Sep 17 00:00:00 2001 From: Olga Maciaszek-Sharma Date: Wed, 17 Feb 2016 22:26:54 +0100 Subject: [PATCH] Started splitting test methods generation implementation into separate cases for Spock and JUnit. --- .../builder/JUnitMethodBodyBuilder.groovy | 67 +++++- .../accurest/builder/MethodBodyBuilder.groovy | 225 ++++++++++++++++++ .../MockMvcJUnitMethodBodyBuilder.groovy | 37 +++ .../builder/SpockMethodBodyBuilder.groovy | 210 +++------------- 4 files changed, 349 insertions(+), 190 deletions(-) create mode 100644 accurest-core/src/main/groovy/io/codearte/accurest/builder/MethodBodyBuilder.groovy create mode 100644 accurest-core/src/main/groovy/io/codearte/accurest/builder/MockMvcJUnitMethodBodyBuilder.groovy diff --git a/accurest-core/src/main/groovy/io/codearte/accurest/builder/JUnitMethodBodyBuilder.groovy b/accurest-core/src/main/groovy/io/codearte/accurest/builder/JUnitMethodBodyBuilder.groovy index 0f31ff8eb8..1b4e08b449 100644 --- a/accurest-core/src/main/groovy/io/codearte/accurest/builder/JUnitMethodBodyBuilder.groovy +++ b/accurest-core/src/main/groovy/io/codearte/accurest/builder/JUnitMethodBodyBuilder.groovy @@ -1,18 +1,65 @@ package io.codearte.accurest.builder +import groovy.json.StringEscapeUtils +import groovy.transform.PackageScope +import groovy.transform.TypeChecked +import io.codearte.accurest.dsl.GroovyDsl +import io.codearte.accurest.dsl.internal.ExecutionProperty + /** * @author Jakub Kubrynski + * @author Olga Maciaszek-Sharma */ -class JUnitMethodBodyBuilder { -/* - given() - .contentType("application/json") - .header("Accept", "application/json") - .body("{'name': 'MyApp', 'description' : 'awesome app'}".replaceAll("'", "\"")). +@TypeChecked +@PackageScope +abstract class JUnitMethodBodyBuilder extends MethodBodyBuilder { - expect() - .statusCode(200).body("id", is(not(nullValue()))). + JUnitMethodBodyBuilder(GroovyDsl stubDefinition) { + super(stubDefinition) + } - when() - .post(root.toString() + "rest/applications").asString();*/ + @Override + protected void when(BlockBuilder bb) { + + } + + @Override + protected String getResponseAsString() { + return null + } + + @Override + protected String addCommentSignIfRequired(String baseString) { + return "// $baseString" + } + + @Override + protected String addColonIfRequired(String baseString) { + return "$baseString;" + } + + @Override + protected String getResponseBodyPropertyComparisonString(String property, String value) { + return "assertThat(responseBody${property}).isEqualTo(\"${value}\");" + } + + @Override + protected String getMultipartParameterLine(Map.Entry parameter) { + return null //TODO + } + + @Override + protected void processBodyElement(BlockBuilder blockBuilder, String property, ExecutionProperty exec) { + blockBuilder.addLine("${exec.insertValue("parsedJson.read(\"\\\$$property\")")};") + } + + @Override + protected String getPropertyInListString(String property, Integer listIndex) { + return "${property}.get($listIndex)" ?: '' + } + + @Override + protected String convertUnicodeEscapesIfRequired(String json) { + return json // TODO: verify if that's fine or escapeJava required + } } diff --git a/accurest-core/src/main/groovy/io/codearte/accurest/builder/MethodBodyBuilder.groovy b/accurest-core/src/main/groovy/io/codearte/accurest/builder/MethodBodyBuilder.groovy new file mode 100644 index 0000000000..443c6cd579 --- /dev/null +++ b/accurest-core/src/main/groovy/io/codearte/accurest/builder/MethodBodyBuilder.groovy @@ -0,0 +1,225 @@ +package io.codearte.accurest.builder + +import groovy.json.JsonOutput +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.QueryParameter +import io.codearte.accurest.dsl.internal.Request +import io.codearte.accurest.dsl.internal.Response +import io.codearte.accurest.util.ContentType +import io.codearte.accurest.util.JsonPaths +import io.codearte.accurest.util.JsonToJsonPathsConverter +import io.codearte.accurest.util.MapConverter + +import static io.codearte.accurest.util.ContentUtils.extractValue +import static io.codearte.accurest.util.ContentUtils.recognizeContentTypeFromContent +import static io.codearte.accurest.util.ContentUtils.recognizeContentTypeFromHeader + +/** + * @author Olga Maciaszek-Sharma + * @since 2016-02-17 + */ +@TypeChecked +@PackageScope +abstract class MethodBodyBuilder { + + protected final Request request + protected final Response response + + MethodBodyBuilder(GroovyDsl stubDefinition) { + this.request = stubDefinition.request + this.response = stubDefinition.response + } + + protected abstract void validateResponseCodeBlock(BlockBuilder bb) + + 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 String getResponseBodyPropertyComparisonString(String property, String value) + + protected abstract String getMultipartParameterLine(Map.Entry parameter) + + protected abstract void processBodyElement(BlockBuilder blockBuilder, String property, ExecutionProperty exec) + + protected abstract void processBodyElement(BlockBuilder blockBuilder, String property, Map.Entry entry) + + protected abstract String getPropertyInListString(String property, Integer index) + + protected abstract String convertUnicodeEscapesIfRequired(String json) + + void appendTo(BlockBuilder blockBuilder) { + blockBuilder.startBlock() + + givenBlock(blockBuilder) + whenBlock(blockBuilder) + thenBlock(blockBuilder) + + blockBuilder.endBlock() + } + protected void thenBlock(BlockBuilder bb) { + bb.addLine(addCommentSignIfRequired('then:')) + bb.startBlock() + then(bb) + bb.endBlock() + } + + protected void whenBlock(BlockBuilder bb) { + bb.addLine(addCommentSignIfRequired('when:')) + bb.startBlock() + when(bb) + bb.endBlock().addEmptyLine() + } + + protected void givenBlock(BlockBuilder bb) { + bb.addLine(addCommentSignIfRequired('given:')) + bb.startBlock() + given(bb) + bb.endBlock().addEmptyLine() + } + + + protected void then(BlockBuilder bb) { + validateResponseCodeBlock(bb) + if (response.headers) { + validateResponseHeadersBlock(bb) + } + if (response.body) { + bb.endBlock() + bb.addLine('and:').startBlock() + validateResponseBodyBlock(bb) + } + } + + private void validateResponseBodyBlock(BlockBuilder bb) { + def responseBody = response.body.serverValue + ContentType contentType = getResponseContentType() + if (responseBody instanceof GString) { + responseBody = extractValue(responseBody, contentType, { DslProperty dslProperty -> dslProperty.serverValue }) + } + if (contentType == ContentType.JSON) { + appendJsonPath(bb, responseAsString) + JsonPaths jsonPaths = JsonToJsonPathsConverter.transformToJsonPathWithTestsSideValues(responseBody) + jsonPaths.each { + bb.addLine("assertThat(parsedJson)" + it.method()) + } + processBodyElement(bb, "", responseBody) + } else if (contentType == ContentType.XML) { + bb.addLine("def responseBody = new XmlSlurper().parseText($responseAsString)") + // TODO xml validation + } else { + bb.addLine("def responseBody = ($responseAsString)") + processText(bb, "", responseBody as String) + } + } + + private ContentType getResponseContentType() { + ContentType contentType = recognizeContentTypeFromHeader(response.headers) + if (contentType == ContentType.UNKNOWN) { + contentType = recognizeContentTypeFromContent(response.body.serverValue) + } + return contentType + } + + protected void appendJsonPath(BlockBuilder blockBuilder, String json) { + blockBuilder.addLine(addColonIfRequired("DocumentContext parsedJson = JsonPath.parse($json)")) + } + + protected void processText(BlockBuilder blockBuilder, String property, String value) { + if (value.startsWith('$')) { + value = value.substring(1).replaceAll('\\$value', "responseBody$property") + blockBuilder.addLine(value) + } else { + blockBuilder.addLine(getResponseBodyPropertyComparisonString(property, value)) + } + } + + protected void processBodyElement(BlockBuilder blockBuilder, String property, Object value) { + } + + protected String getBodyAsString() { + Object bodyValue = extractServerValueFromBody(request.body.serverValue) + String json = new JsonOutput().toJson(bodyValue) + json = convertUnicodeEscapesIfRequired(json) + return trimRepeatedQuotes(json) + } + + protected Map getMultipartParameters() { + return (Map) request?.multipart?.serverValue + } + + protected String trimRepeatedQuotes(String toTrim) { + return toTrim.startsWith('"') ? toTrim.replaceAll('"', '') : toTrim // TODO: implement for JUnit + } + + protected Object extractServerValueFromBody(bodyValue) { + if (bodyValue instanceof GString) { + bodyValue = extractValue(bodyValue, { DslProperty dslProperty -> dslProperty.serverValue }) + } else { + bodyValue = MapConverter.transformValues(bodyValue, { it instanceof DslProperty ? it.serverValue : it }) + } + return bodyValue + } + + protected boolean allowedQueryParameter(QueryParameter param) { + return allowedQueryParameter(param.serverValue) + } + + protected boolean allowedQueryParameter(MatchingStrategy matchingStrategy) { + return matchingStrategy.type != MatchingStrategy.Type.ABSENT + } + + protected boolean allowedQueryParameter(Object o) { + return true + } + + protected String resolveParamValue(QueryParameter param) { + return resolveParamValue(param.serverValue) + } + + protected String resolveParamValue(Object value) { + return value.toString() + } + + protected String resolveParamValue(MatchingStrategy matchingStrategy) { + return matchingStrategy.serverValue.toString() + } + + protected ContentType getRequestContentType() { + ContentType contentType = recognizeContentTypeFromHeader(request.headers) + if (contentType == ContentType.UNKNOWN) { + contentType = recognizeContentTypeFromContent(request.body.serverValue) + } + return contentType + } + + protected String getTestSideValue(Object object) { + return MapConverter.getTestSideValues(object).toString() + } + + protected void processBodyElement(BlockBuilder blockBuilder, String property, Map map) { + map.each { + processBodyElement(blockBuilder, property, it) + } + } + + protected void processBodyElement(BlockBuilder blockBuilder, String property, List list) { + list.eachWithIndex { listElement, listIndex -> + String prop = getPropertyInListString(property, listIndex as Integer) + processBodyElement(blockBuilder, prop, listElement) + } + } +} diff --git a/accurest-core/src/main/groovy/io/codearte/accurest/builder/MockMvcJUnitMethodBodyBuilder.groovy b/accurest-core/src/main/groovy/io/codearte/accurest/builder/MockMvcJUnitMethodBodyBuilder.groovy new file mode 100644 index 0000000000..707a2eae42 --- /dev/null +++ b/accurest-core/src/main/groovy/io/codearte/accurest/builder/MockMvcJUnitMethodBodyBuilder.groovy @@ -0,0 +1,37 @@ +package io.codearte.accurest.builder + +import io.codearte.accurest.dsl.GroovyDsl +import io.codearte.accurest.dsl.internal.Header + +import java.util.regex.Pattern + +/** + * @author Olga Maciaszek-Sharma + * @since 2016-02-17 + */ +class MockMvcJUnitMethodBodyBuilder extends JUnitMethodBodyBuilder{ + + MockMvcJUnitMethodBodyBuilder(GroovyDsl stubDefinition) { + super(stubDefinition) + } + + @Override + protected void validateResponseCodeBlock(BlockBuilder bb) { + bb.addLine("assertThat(response.statusCode()).isEqualTo($response.status.serverValue);") + } + + @Override + protected void validateResponseHeadersBlock(BlockBuilder bb) { + response.headers?.collect { Header header -> + bb.addLine("assertThat(response.header(\"$header.name\")).${createHeaderComparison(header.serverValue)}") + } + } + + private String createHeaderComparison(Object headerValue) { + return "isEqualTo(\"$headerValue\");" + } + + private String createHeaderComparison(Pattern headerValue) { + return "matches(\"$headerValue\");" + } +} diff --git a/accurest-core/src/main/groovy/io/codearte/accurest/builder/SpockMethodBodyBuilder.groovy b/accurest-core/src/main/groovy/io/codearte/accurest/builder/SpockMethodBodyBuilder.groovy index c5202cad39..dce3ad6910 100644 --- a/accurest-core/src/main/groovy/io/codearte/accurest/builder/SpockMethodBodyBuilder.groovy +++ b/accurest-core/src/main/groovy/io/codearte/accurest/builder/SpockMethodBodyBuilder.groovy @@ -5,219 +5,69 @@ import groovy.json.StringEscapeUtils import groovy.transform.PackageScope import groovy.transform.TypeChecked import io.codearte.accurest.dsl.GroovyDsl -import io.codearte.accurest.dsl.internal.* +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.NamedProperty +import io.codearte.accurest.dsl.internal.QueryParameter import io.codearte.accurest.util.ContentType import io.codearte.accurest.util.MapConverter -import io.codearte.accurest.util.JsonToJsonPathsConverter -import io.codearte.accurest.util.JsonPaths -import static io.codearte.accurest.util.ContentUtils.* +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 */ @PackageScope @TypeChecked -abstract class SpockMethodBodyBuilder { - - protected final Request request - protected final Response response +abstract class SpockMethodBodyBuilder extends MethodBodyBuilder { SpockMethodBodyBuilder(GroovyDsl stubDefinition) { - this.request = stubDefinition.request - this.response = stubDefinition.response + super(stubDefinition) } - void appendTo(BlockBuilder blockBuilder) { - blockBuilder.startBlock() - - givenBlock(blockBuilder) - whenBlock(blockBuilder) - thenBlock(blockBuilder) - - blockBuilder.endBlock() - } - - protected void thenBlock(BlockBuilder bb) { - bb.addLine('then:') - bb.startBlock() - then(bb) - bb.endBlock() - } - - protected void whenBlock(BlockBuilder bb) { - bb.addLine('when:') - bb.startBlock() - when(bb) - bb.endBlock().addEmptyLine() - } - - protected void givenBlock(BlockBuilder bb) { - bb.addLine('given:') - bb.startBlock() - given(bb) - bb.endBlock().addEmptyLine() - } - - protected void given(BlockBuilder bb) {} - - protected abstract void when(BlockBuilder bb) - - protected abstract void validateResponseCodeBlock(BlockBuilder bb) - - protected abstract void validateResponseHeadersBlock(BlockBuilder bb) - - protected abstract String getResponseAsString() - - protected void then(BlockBuilder bb) { - validateResponseCodeBlock(bb) - if (response.headers) { - validateResponseHeadersBlock(bb) - } - if (response.body) { - bb.endBlock() - bb.addLine('and:').startBlock() - validateResponseBodyBlock(bb) - } - } - - protected void validateResponseBodyBlock(BlockBuilder bb) { - def responseBody = response.body.serverValue - ContentType contentType = getResponseContentType() - if (responseBody instanceof GString) { - responseBody = extractValue(responseBody, contentType, { DslProperty dslProperty -> dslProperty.serverValue }) - } - if (contentType == ContentType.JSON) { - appendJsonPath(bb, responseAsString) - JsonPaths jsonPaths = JsonToJsonPathsConverter.transformToJsonPathWithTestsSideValues(responseBody) - jsonPaths.each { - bb.addLine("assertThat(parsedJson)" + it.method()) - } - processBodyElement(bb, "", responseBody) - } else if (contentType == ContentType.XML) { - bb.addLine("def responseBody = new XmlSlurper().parseText($responseAsString)") - // TODO xml validation - } else { - bb.addLine("def responseBody = ($responseAsString)") - processText(bb, "", responseBody as String) - } - } - - protected void processText(BlockBuilder blockBuilder, String property, String value) { - if (value.startsWith('$')) { - value = value.substring(1).replaceAll('\\$value', "responseBody$property") - blockBuilder.addLine(value) - } else { - blockBuilder.addLine("responseBody$property == \"${value}\"") - } - } - - protected String - - protected String getBodyAsString() { - Object bodyValue = extractServerValueFromBody(request.body.serverValue) - String json = new JsonOutput().toJson(bodyValue) - json = convertUnicodeEscapes(json) - return trimRepeatedQuotes(json) - } - - protected Map getMultipartParameters() { - return (Map)request?.multipart?.serverValue + @Override + protected String getResponseBodyPropertyComparisonString(String property, String value) { + return "responseBody$property == \"${value}\"" } + @Override protected String getMultipartParameterLine(Map.Entry parameter) { - if (parameter.value instanceof NamedProperty) { + if (parameter.value instanceof NamedProperty) { return ".multiPart(${getMultipartFileParameterContent(parameter.key, (NamedProperty) parameter.value)})" } return ".param('$parameter.key', '$parameter.value')" } - protected String convertUnicodeEscapes(String json) { - return StringEscapeUtils.unescapeJavaScript(json) - } - - protected String trimRepeatedQuotes(String toTrim) { - return toTrim.startsWith('"') ? toTrim.replaceAll('"', '') : toTrim - } - - protected Object extractServerValueFromBody(bodyValue) { - if (bodyValue instanceof GString) { - bodyValue = extractValue(bodyValue, { DslProperty dslProperty -> dslProperty.serverValue }) - } else { - bodyValue = MapConverter.transformValues(bodyValue, { it instanceof DslProperty ? it.serverValue : it }) - } - return bodyValue - } - - protected boolean allowedQueryParameter(QueryParameter param) { - return allowedQueryParameter(param.serverValue) - } - - protected boolean allowedQueryParameter(MatchingStrategy matchingStrategy) { - return matchingStrategy.type != MatchingStrategy.Type.ABSENT - } - - protected boolean allowedQueryParameter(Object o) { - return true - } - - protected String resolveParamValue(QueryParameter param) { - return resolveParamValue(param.serverValue) - } - - protected String resolveParamValue(Object value) { - return value.toString() - } - - protected String resolveParamValue(MatchingStrategy matchingStrategy) { - return matchingStrategy.serverValue.toString() - } - - protected void processBodyElement(BlockBuilder blockBuilder, String property, Object value) { - - } - - protected void appendJsonPath(BlockBuilder blockBuilder, String json) { - blockBuilder.addLine("DocumentContext parsedJson = JsonPath.parse($json)") - } - + @Override protected void processBodyElement(BlockBuilder blockBuilder, String property, ExecutionProperty exec) { blockBuilder.addLine("${exec.insertValue("parsedJson.read('\\\$$property')")}") } + @Override protected void processBodyElement(BlockBuilder blockBuilder, String property, Map.Entry entry) { processBodyElement(blockBuilder, property + "." + entry.key, entry.value) } - protected void processBodyElement(BlockBuilder blockBuilder, String property, Map map) { - map.each { - processBodyElement(blockBuilder, property, it) - } + @Override + protected String addCommentSignIfRequired(String baseString) { + return baseString } - protected void processBodyElement(BlockBuilder blockBuilder, String property, List list) { - list.eachWithIndex { listElement, listIndex -> - String prop = "$property[$listIndex]" ?: '' - processBodyElement(blockBuilder, prop, listElement) - } + @Override + protected String addColonIfRequired(String baseString) { + return baseString } - protected ContentType getRequestContentType() { - ContentType contentType = recognizeContentTypeFromHeader(request.headers) - if (contentType == ContentType.UNKNOWN) { - contentType = recognizeContentTypeFromContent(request.body.serverValue) - } - return contentType + @Override + protected String getPropertyInListString(String property, Integer listIndex) { + "$property[$listIndex]" ?: '' } - protected ContentType getResponseContentType() { - ContentType contentType = recognizeContentTypeFromHeader(response.headers) - if (contentType == ContentType.UNKNOWN) { - contentType = recognizeContentTypeFromContent(response.body.serverValue) - } - return contentType - } - - protected String getTestSideValue(Object object) { - return MapConverter.getTestSideValues(object).toString() + protected String convertUnicodeEscapesIfRequired(String json) { + return StringEscapeUtils.unescapeJavaScript(json) } }