Started splitting test methods generation implementation into separate cases for Spock and JUnit.

This commit is contained in:
Olga Maciaszek-Sharma
2016-02-17 22:26:54 +01:00
parent 97f03964bc
commit 661c0dcbd7
4 changed files with 349 additions and 190 deletions

View File

@@ -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<String, Object> 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
}
}

View File

@@ -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<String, Object> 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<String, Object> getMultipartParameters() {
return (Map<String, Object>) 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)
}
}
}

View File

@@ -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\");"
}
}

View File

@@ -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<String, Object> getMultipartParameters() {
return (Map<String, Object>)request?.multipart?.serverValue
@Override
protected String getResponseBodyPropertyComparisonString(String property, String value) {
return "responseBody$property == \"${value}\""
}
@Override
protected String getMultipartParameterLine(Map.Entry<String, Object> 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)
}
}