[Messaging] Generates tests on the server side

WIP on #234
This commit is contained in:
Marcin Grzejszczak
2016-04-20 11:32:47 +02:00
parent ff96e235b1
commit e1bde47618
128 changed files with 4423 additions and 331 deletions

3
.gitignore vendored
View File

@@ -7,4 +7,5 @@ target/
build/
hs_err_pid*
.DS_Store
.DS_Store
*.log

View File

@@ -35,11 +35,14 @@ class RecursiveFilesConverter {
return
}
String convertedContent = singleFileConverter.convertContent(entry.key.last().toString(), contract)
if (!convertedContent) {
return
}
Path absoluteTargetPath = createAndReturnTargetDirectory(sourceFile)
File newGroovyFile = createTargetFileWithProperName(absoluteTargetPath, sourceFile)
newGroovyFile.setText(convertedContent, StandardCharsets.UTF_8.toString())
} catch (Exception e) {
throw new ConversionAccurestException("Unable to make convertion of ${sourceFile.name}", e)
throw new ConversionAccurestException("Unable to make conversion of ${sourceFile.name}", e)
}
}
}
@@ -49,12 +52,12 @@ class RecursiveFilesConverter {
Path relativePath = Paths.get(properties.contractsDslDir.toURI()).relativize(sourceFile.parentFile.toPath())
Path absoluteTargetPath = properties.stubsOutputDir.toPath().resolve(relativePath)
Files.createDirectories(absoluteTargetPath)
absoluteTargetPath
return absoluteTargetPath
}
private File createTargetFileWithProperName(Path absoluteTargetPath, File sourceFile) {
File newGroovyFile = new File(absoluteTargetPath.toFile(), singleFileConverter.generateOutputFileNameForInput(sourceFile.name))
log.info("Creating new json [$newGroovyFile.path]")
newGroovyFile
return newGroovyFile
}
}

View File

@@ -28,7 +28,7 @@ class RecursiveFilesConverterSpec extends Specification {
and:
def singleFileConverterStub = Stub(SingleFileConverter)
singleFileConverterStub.canHandleFileName(_) >> { String fileName -> fileName.endsWith(".groovy") }
singleFileConverterStub.convertContent(_) >> { "converted" }
singleFileConverterStub.convertContent(_, _) >> { "converted" }
singleFileConverterStub.generateOutputFileNameForInput(_) >> { String inputFileName -> inputFileName.replaceAll('.groovy', '.json') }
RecursiveFilesConverter recursiveFilesConverter = new RecursiveFilesConverter(singleFileConverterStub, properties)
@@ -53,7 +53,7 @@ class RecursiveFilesConverterSpec extends Specification {
and:
def singleFileConverterStub = Stub(SingleFileConverter)
singleFileConverterStub.canHandleFileName(_) >> { String fileName -> fileName.endsWith(".groovy") }
singleFileConverterStub.convertContent(_) >> { "converted" }
singleFileConverterStub.convertContent(_, _) >> { "converted" }
singleFileConverterStub.generateOutputFileNameForInput(_) >> { String inputFileName -> inputFileName.replaceAll('.groovy', '.json') }
RecursiveFilesConverter recursiveFilesConverter = new RecursiveFilesConverter(singleFileConverterStub, properties)

View File

@@ -1,12 +1,15 @@
package io.codearte.accurest
import groovy.transform.Canonical
import groovy.transform.PackageScope
import groovy.util.logging.Slf4j
import io.codearte.accurest.builder.ClassBuilder
import io.codearte.accurest.config.AccurestConfigProperties
import io.codearte.accurest.config.TestFramework
import io.codearte.accurest.config.TestMode
import io.codearte.accurest.dsl.GroovyDsl
import io.codearte.accurest.file.Contract
import org.codehaus.groovy.control.CompilerConfiguration
import static io.codearte.accurest.builder.ClassBuilder.createClass
import static io.codearte.accurest.builder.MethodBuilder.createTestMethod
@@ -49,50 +52,88 @@ class SingleTestGenerator {
clazz.addClassLevelAnnotation(configProperties.targetFramework.getOrderAnnotation())
}
if (configProperties.testMode == TestMode.JAXRSCLIENT) {
clazz.addStaticImport('javax.ws.rs.client.Entity.*')
if (configProperties.targetFramework == TestFramework.JUNIT) {
clazz.addImport('javax.ws.rs.core.Response')
}
} else if (configProperties.testMode == TestMode.MOCKMVC) {
clazz.addStaticImport('com.jayway.restassured.module.mockmvc.RestAssuredMockMvc.*')
} else {
clazz.addStaticImport('com.jayway.restassured.RestAssured.*')
}
if (configProperties.targetFramework == TestFramework.JUNIT) {
if (configProperties.testMode == TestMode.MOCKMVC) {
clazz.addImport('com.jayway.restassured.module.mockmvc.specification.MockMvcRequestSpecification')
clazz.addImport('com.jayway.restassured.response.ResponseOptions')
}
clazz.addImport('org.junit.Test')
clazz.addStaticImport('org.assertj.core.api.Assertions.assertThat')
}
if (configProperties.ruleClassForTests) {
clazz.addImport('org.junit.Rule').addRule(configProperties.ruleClassForTests)
}
addJsonPathRelatedImports(clazz)
listOfFiles.each {
clazz.addMethod(createTestMethod(it, configProperties))
Map<ParsedDsl, TestType> contracts = listOfFiles.collectEntries {
File stubsFile = it.path.toFile()
log.debug("Stub content from file [${stubsFile.text}]")
GroovyDsl stubContent = new GroovyShell(delegate.class.classLoader, new Binding(), new CompilerConfiguration(sourceEncoding:'UTF-8')).evaluate(stubsFile)
TestType testType = (stubContent.inputMessage || stubContent.outputMessage) ? TestType.MESSAGING : TestType.HTTP
return [(new ParsedDsl(it, stubContent, stubsFile)) : testType]
}
boolean conditionalImportsAdded = false
contracts.each { ParsedDsl key, TestType value ->
if (!conditionalImportsAdded) {
if (value == TestType.HTTP) {
if (configProperties.testMode == TestMode.JAXRSCLIENT) {
clazz.addStaticImport('javax.ws.rs.client.Entity.*')
if (configProperties.targetFramework == TestFramework.JUNIT) {
clazz.addImport('javax.ws.rs.core.Response')
}
} else if (configProperties.testMode == TestMode.MOCKMVC) {
clazz.addStaticImport('com.jayway.restassured.module.mockmvc.RestAssuredMockMvc.*')
} else {
clazz.addStaticImport('com.jayway.restassured.RestAssured.*')
}
}
if (configProperties.targetFramework == TestFramework.JUNIT) {
if (value == TestType.HTTP && configProperties.testMode == TestMode.MOCKMVC) {
clazz.addImport('com.jayway.restassured.module.mockmvc.specification.MockMvcRequestSpecification')
clazz.addImport('com.jayway.restassured.response.ResponseOptions')
}
clazz.addImport('org.junit.Test')
clazz.addStaticImport('org.assertj.core.api.Assertions.assertThat')
}
if (configProperties.ruleClassForTests) {
clazz.addImport('org.junit.Rule').addRule(configProperties.ruleClassForTests)
}
if (value == TestType.MESSAGING) {
addMessagingRelatedEntries(clazz)
}
conditionalImportsAdded = true
}
clazz.addMethod(createTestMethod(key.contract, key.stubsFile, key.groovyDsl, configProperties))
}
return clazz.build()
}
@Canonical
private static class ParsedDsl {
Contract contract
GroovyDsl groovyDsl
File stubsFile
}
private static enum TestType {
MESSAGING, HTTP
}
private boolean isScenarioClass(Collection<Contract> listOfFiles) {
listOfFiles.find({ it.order != null }) != null
}
private ClassBuilder addJsonPathRelatedImports(ClassBuilder clazz) {
clazz.addImport(['com.jayway.jsonpath.DocumentContext',
'com.jayway.jsonpath.JsonPath'])
'com.jayway.jsonpath.JsonPath',
])
if (jsonAssertPresent()) {
clazz.addStaticImport(JSON_ASSERT_STATIC_IMPORT)
}
}
private ClassBuilder addMessagingRelatedEntries(ClassBuilder clazz) {
clazz.addField(['@Inject AccurestMessaging accurestMessaging',
'ObjectMapper accurestObjectMapper = new ObjectMapper()'
])
clazz.addImport([ 'javax.inject.Inject',
'com.fasterxml.jackson.databind.ObjectMapper',
'io.codearte.accurest.messaging.AccurestMessage',
'io.codearte.accurest.messaging.AccurestMessaging',
])
clazz.addStaticImport('io.codearte.accurest.messaging.AccurestMessagingUtil.headers')
}
private static boolean jsonAssertPresent() {
try {
Class.forName(JSON_ASSERT_CLASS)

View File

@@ -3,7 +3,6 @@ package io.codearte.accurest.builder
import io.codearte.accurest.config.AccurestConfigProperties
import io.codearte.accurest.config.TestFramework
import io.codearte.accurest.util.NamesUtil
/**
* @author Jakub Kubrynski
*/
@@ -15,6 +14,7 @@ class ClassBuilder {
private final List<String> imports = []
private final List<String> staticImports = []
private final List<String> rules = []
private final List<String> fields = []
private final List<MethodBuilder> methods = []
private final List<String> classLevelAnnotations = []
private final TestFramework lang
@@ -49,6 +49,7 @@ class ClassBuilder {
return this
}
ClassBuilder addStaticImport(String importToAdd) {
staticImports << importToAdd
return this
@@ -59,6 +60,23 @@ class ClassBuilder {
return this
}
ClassBuilder addField(String fieldToAdd) {
fields << appendColonIfJUniTest(fieldToAdd)
return this
}
private String appendColonIfJUniTest(String field) {
if (lang == TestFramework.JUNIT && !field.endsWith(';')) {
return "$field;"
}
return field
}
ClassBuilder addField(List<String> fieldsToAdd) {
fields.addAll(fieldsToAdd.collect { appendColonIfJUniTest(it) })
return this
}
ClassBuilder addRule(String ruleClass) {
imports << ruleClass
rules << NamesUtil.afterLastDot(ruleClass)
@@ -105,6 +123,13 @@ class ClassBuilder {
clazz.addEmptyLine()
}
fields.sort().each {
clazz.addLine(it)
}
if (!fields.empty) {
clazz.addEmptyLine()
}
methods.each {
clazz.addBlock(it)
}

View File

@@ -0,0 +1,166 @@
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
import io.codearte.accurest.dsl.internal.Header
import io.codearte.accurest.dsl.internal.Input
import io.codearte.accurest.dsl.internal.NamedProperty
import java.util.regex.Pattern
import static io.codearte.accurest.config.TestFramework.JUNIT
/**
* @author Jakub Kubrynski
*/
@PackageScope
@TypeChecked
class JUnitMessagingMethodBodyBuilder extends MessagingMethodBodyBuilder {
JUnitMessagingMethodBodyBuilder(GroovyDsl stubDefinition) {
super(stubDefinition)
}
@Override
protected String getInputString(Input request) {
if (request.triggeredBy) {
return request.triggeredBy.executionCommand
}
return "accurestMessaging.send(inputMessage, \"${request.messageFrom}\")"
}
@Override
protected String getResponseBodyPropertyComparisonString(String property, String value) {
return "responseBody$property == \"${value}\""
}
@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)
}
@Override
protected void processHeaderElement(BlockBuilder blockBuilder, String property, String value) {
blockBuilder.addLine("assertThat(response.getHeader(\"$property\")).${createHeaderComparison(value)}")
}
@Override
protected void processHeaderElement(BlockBuilder blockBuilder, String property, Pattern pattern) {
blockBuilder.addLine("assertThat(response.getHeader(\"$property\")).${createHeaderComparison(pattern)}")
}
@Override
protected void processHeaderElement(BlockBuilder blockBuilder, String property, ExecutionProperty exec) {
blockBuilder.addLine("${exec.insertValue("response.getHeader(\"$property\")")};")
}
@Override
protected void validateResponseCodeBlock(BlockBuilder bb) {
}
@Override
protected void validateResponseHeadersBlock(BlockBuilder bb) {
bb.addLine("""AccurestMessage response = accurestMessaging.receiveMessage("${outputMessage.sentTo}");""")
outputMessage.headers?.collect { Header header ->\
processHeaderElement(bb, header.name, header.serverValue)
}
}
@Override
protected String getResponseAsString() {
return 'accurestObjectMapper.writeValueAsString(response.getPayload())'
}
@Override
protected String addCommentSignIfRequired(String baseString) {
return "// $baseString"
}
@Override
protected BlockBuilder addColonIfRequired(BlockBuilder blockBuilder) {
blockBuilder.addAtTheEnd(JUNIT.lineSuffix)
return blockBuilder
}
@Override
protected String getPropertyInListString(String property, Integer listIndex) {
return "$property[$listIndex]" ?: ''
}
@Override
protected String convertUnicodeEscapesIfRequired(String json) {
return StringEscapeUtils.unescapeJavaScript(json)
}
@Override
protected String getParsedXmlResponseBodyString(String responseString) {
return "Object responseBody = new XmlSlurper().parseText($responseString);"
}
@Override
protected String getSimpleResponseBodyString(String responseString) {
return "Object responseBody = ($responseString);"
}
@Override
protected String getInputString() {
String request = 'AccurestMessage inputMessage = accurestMessaging.create('
if (inputMessage.messageBody) {
request = "${request}\n\t\t\t\"${StringEscapeUtils.escapeJava(bodyAsString)}\"\n\t\t"
}
if (inputMessage.messageHeaders) {
request = "${request}, headers()\n"
}
inputMessage.messageHeaders?.collect { Header header ->
request = "${request}\t\t\t${getHeaderString(header)}"
}
return "${request})"
}
@Override
protected String getHeaderString(Header header) {
return ".header(\"${getTestSideValue(header.name)}\", \"${getTestSideValue(header.serverValue)}\")"
}
@Override
protected String getBodyString(String bodyAsString) {
return ''
}
@Override
protected String getMultipartFileParameterContent(String propertyName, NamedProperty propertyValue) {
return ""
}
@Override
protected String getParameterString(Map.Entry<String, Object> parameter) {
return ""
}
protected String convertHeaderComparison(String headerValue) {
return " == '$headerValue'"
}
protected String convertHeaderComparison(Pattern headerValue) {
return "==~ java.util.regex.Pattern.compile('$headerValue')"
}
protected String createHeaderComparison(Object headerValue) {
String escapedHeader = convertUnicodeEscapesIfRequired("$headerValue")
return "isEqualTo(\"$escapedHeader\");"
}
protected String createHeaderComparison(Pattern headerValue) {
String escapedHeader = convertUnicodeEscapesIfRequired("$headerValue")
return "matches(\"$escapedHeader\");"
}
}

View File

@@ -21,7 +21,7 @@ import static io.codearte.accurest.util.ContentUtils.getJavaMultipartFileParamet
*/
@TypeChecked
@PackageScope
abstract class JUnitMethodBodyBuilder extends MethodBodyBuilder {
abstract class JUnitMethodBodyBuilder extends RequestProcessingMethodBodyBuilder {
JUnitMethodBodyBuilder(GroovyDsl stubDefinition) {
super(stubDefinition)
@@ -87,12 +87,12 @@ abstract class JUnitMethodBodyBuilder extends MethodBodyBuilder {
}
@Override
protected String getResponseString(Request request) {
protected String getInputString(Request request) {
return 'ResponseOptions response = given().spec(request)'
}
@Override
protected String getRequestString() {
protected String getInputString() {
return 'MockMvcRequestSpecification request = given()'
}

View File

@@ -12,9 +12,9 @@ import java.util.regex.Pattern
@PackageScope
@TypeChecked
class JaxRsClientSpockMethodBodyBuilder extends SpockMethodBodyBuilder {
class JaxRsClientSpockMethodRequestProcessingBodyBuilder extends SpockMethodRequestProcessingBodyBuilder {
JaxRsClientSpockMethodBodyBuilder(GroovyDsl stubDefinition) {
JaxRsClientSpockMethodRequestProcessingBodyBuilder(GroovyDsl stubDefinition) {
super(stubDefinition)
}

View File

@@ -0,0 +1,87 @@
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.Input
import io.codearte.accurest.dsl.internal.OutputMessage
import io.codearte.accurest.util.ContentType
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 MessagingMethodBodyBuilder extends MethodBodyBuilder {
protected final Input inputMessage
protected final OutputMessage outputMessage
MessagingMethodBodyBuilder(GroovyDsl stubDefinition) {
this.inputMessage = stubDefinition.inputMessage
this.outputMessage = stubDefinition.outputMessage
}
protected abstract String getInputString(Input request)
@Override
protected boolean hasGivenSection() {
return !inputMessage.triggeredBy
}
protected void processInput(BlockBuilder bb) {
}
protected void when(BlockBuilder bb) {
bb.addLine(getInputString(inputMessage))
bb.indent()
addColonIfRequired(bb)
bb.unindent()
}
protected void then(BlockBuilder bb) {
validateResponseCodeBlock(bb)
if (inputMessage.assertThat) {
bb.addLine(inputMessage.assertThat.executionCommand)
addColonIfRequired(bb)
}
if (outputMessage) {
if (outputMessage.headers) {
validateResponseHeadersBlock(bb)
}
if (outputMessage.body) {
bb.endBlock()
if (outputMessage.headers) {
bb.addLine(addCommentSignIfRequired('and:')).startBlock()
}
validateResponseBodyBlock(bb, outputMessage.body.serverValue)
}
if (outputMessage.assertThat) {
bb.addLine(outputMessage.assertThat.executionCommand)
addColonIfRequired(bb)
}
}
}
protected ContentType getResponseContentType() {
ContentType contentType = recognizeContentTypeFromHeader(outputMessage.headers)
if (contentType == ContentType.UNKNOWN) {
contentType = recognizeContentTypeFromContent(outputMessage.body.serverValue)
}
return contentType
}
protected String getBodyAsString() {
Object bodyValue = extractServerValueFromBody(inputMessage.messageBody.serverValue)
String json = new JsonOutput().toJson(bodyValue)
json = convertUnicodeEscapesIfRequired(json)
return trimRepeatedQuotes(json)
}
}

View File

@@ -1,19 +1,8 @@
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.NamedProperty
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.dsl.internal.*
import io.codearte.accurest.util.ContentType
import io.codearte.accurest.util.JsonPaths
import io.codearte.accurest.util.JsonToJsonPathsConverter
@@ -22,9 +11,6 @@ import io.codearte.accurest.util.MapConverter
import java.util.regex.Pattern
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
@@ -33,14 +19,6 @@ import static io.codearte.accurest.util.ContentUtils.recognizeContentTypeFromHea
@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)
@@ -71,9 +49,7 @@ abstract class MethodBodyBuilder {
protected abstract String getSimpleResponseBodyString(String responseString)
protected abstract String getResponseString(Request request)
protected abstract String getRequestString()
protected abstract String getInputString()
protected abstract String getHeaderString(Header header)
@@ -83,30 +59,30 @@ abstract class MethodBodyBuilder {
protected abstract String getParameterString(Map.Entry<String, Object> parameter)
protected abstract void processInput(BlockBuilder bb)
protected abstract void when(BlockBuilder bb)
protected abstract void then(BlockBuilder bb)
protected abstract ContentType getResponseContentType()
protected abstract String getBodyAsString()
protected abstract boolean hasGivenSection()
void appendTo(BlockBuilder blockBuilder) {
blockBuilder.startBlock()
givenBlock(blockBuilder)
if (hasGivenSection()) {
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()
@@ -114,48 +90,29 @@ abstract class MethodBodyBuilder {
bb.endBlock().addEmptyLine()
}
protected void whenBlock(BlockBuilder bb) {
bb.addLine(addCommentSignIfRequired('when:'))
bb.startBlock()
when(bb)
bb.endBlock().addEmptyLine()
}
protected void thenBlock(BlockBuilder bb) {
bb.addLine(addCommentSignIfRequired('then:'))
bb.startBlock()
then(bb)
bb.endBlock()
}
protected void given(BlockBuilder bb) {
bb.addLine(getRequestString())
bb.addLine(getInputString())
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)) }
}
processInput(bb)
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")/)
addColonIfRequired(bb)
bb.unindent()
}
protected void then(BlockBuilder bb) {
validateResponseCodeBlock(bb)
if (response.headers) {
validateResponseHeadersBlock(bb)
}
if (response.body) {
bb.endBlock()
bb.addLine(addCommentSignIfRequired('and:')).startBlock()
validateResponseBodyBlock(bb)
}
}
private void validateResponseBodyBlock(BlockBuilder bb) {
def responseBody = response.body.serverValue
protected void validateResponseBodyBlock(BlockBuilder bb, Object responseBody) {
ContentType contentType = getResponseContentType()
if (responseBody instanceof GString) {
responseBody = extractValue(responseBody, contentType, { DslProperty dslProperty -> dslProperty.serverValue })
@@ -179,14 +136,6 @@ abstract class MethodBodyBuilder {
}
}
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(("DocumentContext parsedJson = JsonPath.parse($json)"))
addColonIfRequired(blockBuilder)
@@ -212,17 +161,6 @@ abstract class MethodBodyBuilder {
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
}
@@ -236,18 +174,6 @@ abstract class MethodBodyBuilder {
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)
}
@@ -260,14 +186,6 @@ abstract class MethodBodyBuilder {
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()
}
@@ -285,38 +203,5 @@ abstract class MethodBodyBuilder {
}
}
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)
}
protected String getMultipartParameterLine(Map.Entry<String, Object> parameter) {
if (parameter.value instanceof NamedProperty) {
return ".multiPart(${getMultipartFileParameterContent(parameter.key, (NamedProperty) parameter.value)})"
}
return getParameterString(parameter)
}
private boolean hasQueryParams(Url url) {
return url.queryParameters
}
}

View File

@@ -7,8 +7,6 @@ import io.codearte.accurest.config.TestMode
import io.codearte.accurest.dsl.GroovyDsl
import io.codearte.accurest.file.Contract
import io.codearte.accurest.util.NamesUtil
import org.codehaus.groovy.control.CompilerConfiguration
/**
* @author Jakub Kubrynski
*/
@@ -27,10 +25,7 @@ class MethodBuilder {
this.configProperties = configProperties
}
static MethodBuilder createTestMethod(Contract contract, AccurestConfigProperties configProperties) {
File stubsFile = contract.path.toFile()
log.debug("Stub content from file [${stubsFile.text}]")
GroovyDsl stubContent = new GroovyShell(this.classLoader, new Binding(), new CompilerConfiguration(sourceEncoding:'UTF-8')).evaluate(stubsFile)
static MethodBuilder createTestMethod(Contract contract, File stubsFile, GroovyDsl stubContent, AccurestConfigProperties configProperties) {
log.debug("Stub content Groovy DSL [$stubContent]")
String methodName = NamesUtil.camelCase(NamesUtil.toLastDot(NamesUtil.afterLast(stubsFile.path, File.separator)))
return new MethodBuilder(methodName, stubContent, configProperties, contract.ignored)
@@ -43,12 +38,18 @@ class MethodBuilder {
if (ignored) {
blockBuilder.addLine('@Ignore')
}
blockBuilder.addLine(configProperties.targetFramework.methodModifier + "validate_$methodName() {")
blockBuilder.addLine(configProperties.targetFramework.methodModifier + "validate_$methodName() throws Exception {")
getMethodBodyBuilder().appendTo(blockBuilder)
blockBuilder.addLine('}')
}
private MethodBodyBuilder getMethodBodyBuilder() {
if (stubContent.inputMessage || stubContent.outputMessage) {
if (configProperties.targetFramework == TestFramework.JUNIT){
return new JUnitMessagingMethodBodyBuilder(stubContent)
}
return new SpockMessagingMethodBodyBuilder(stubContent)
}
if (configProperties.testMode == TestMode.MOCKMVC && configProperties.targetFramework == TestFramework.JUNIT){
return new MockMvcJUnitMethodBodyBuilder(stubContent)
}
@@ -56,9 +57,9 @@ class MethodBuilder {
if (configProperties.targetFramework == TestFramework.JUNIT){
return new JaxRsClientJUnitMethodBodyBuilder(stubContent)
}
return new JaxRsClientSpockMethodBodyBuilder(stubContent)
return new JaxRsClientSpockMethodRequestProcessingBodyBuilder(stubContent)
}
return new MockMvcSpockMethodBodyBuilder(stubContent)
return new MockMvcSpockMethodRequestProcessingBodyBuilder(stubContent)
}
}

View File

@@ -10,9 +10,9 @@ import java.util.regex.Pattern
@PackageScope
@TypeChecked
class MockMvcSpockMethodBodyBuilder extends SpockMethodBodyBuilder {
class MockMvcSpockMethodRequestProcessingBodyBuilder extends SpockMethodRequestProcessingBodyBuilder {
MockMvcSpockMethodBodyBuilder(GroovyDsl stubDefinition) {
MockMvcSpockMethodRequestProcessingBodyBuilder(GroovyDsl stubDefinition) {
super(stubDefinition)
}

View File

@@ -0,0 +1,152 @@
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.Header
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.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.MapConverter
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 RequestProcessingMethodBodyBuilder extends MethodBodyBuilder {
protected final Request request
protected final Response response
RequestProcessingMethodBodyBuilder(GroovyDsl stubDefinition) {
this.request = stubDefinition.request
this.response = stubDefinition.response
}
protected abstract String getInputString(Request request)
@Override
protected boolean hasGivenSection() {
return request.headers || request.body
}
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 void processInput(BlockBuilder bb) {
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)) }
}
}
protected void when(BlockBuilder bb) {
bb.addLine(getInputString(request))
bb.indent()
String url = buildUrl(request)
String method = request.method.serverValue.toString().toLowerCase()
bb.addLine(/.${method}("$url")/)
addColonIfRequired(bb)
bb.unindent()
}
protected void then(BlockBuilder bb) {
validateResponseCodeBlock(bb)
if (response.headers) {
validateResponseHeadersBlock(bb)
}
if (response.body) {
bb.endBlock()
bb.addLine(addCommentSignIfRequired('and:')).startBlock()
validateResponseBodyBlock(bb, response.body.serverValue)
}
}
protected ContentType getResponseContentType() {
ContentType contentType = recognizeContentTypeFromHeader(response.headers)
if (contentType == ContentType.UNKNOWN) {
contentType = recognizeContentTypeFromContent(response.body.serverValue)
}
return contentType
}
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 ContentType getRequestContentType() {
ContentType contentType = recognizeContentTypeFromHeader(request.headers)
if (contentType == ContentType.UNKNOWN) {
contentType = recognizeContentTypeFromContent(request.body.serverValue)
}
return contentType
}
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)
}
protected String getMultipartParameterLine(Map.Entry<String, Object> parameter) {
if (parameter.value instanceof NamedProperty) {
return ".multiPart(${getMultipartFileParameterContent(parameter.key, (NamedProperty) parameter.value)})"
}
return getParameterString(parameter)
}
private boolean hasQueryParams(Url url) {
return url.queryParameters
}
}

View File

@@ -0,0 +1,161 @@
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
import io.codearte.accurest.dsl.internal.Header
import io.codearte.accurest.dsl.internal.Input
import io.codearte.accurest.dsl.internal.NamedProperty
import java.util.regex.Pattern
/**
* @author Jakub Kubrynski
*/
@PackageScope
@TypeChecked
class SpockMessagingMethodBodyBuilder extends MessagingMethodBodyBuilder {
SpockMessagingMethodBodyBuilder(GroovyDsl stubDefinition) {
super(stubDefinition)
}
@Override
protected String getInputString(Input request) {
if (request.triggeredBy) {
return request.triggeredBy.executionCommand
}
return "accurestMessaging.send(inputMessage, '${request.messageFrom}')"
}
@Override
protected String getResponseBodyPropertyComparisonString(String property, String value) {
return "responseBody$property == \"${value}\""
}
@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)
}
@Override
protected void processHeaderElement(BlockBuilder blockBuilder, String property, ExecutionProperty exec) {
blockBuilder.addLine("${exec.insertValue("response.getHeader(\'$property\')")}")
}
@Override
protected void processHeaderElement(BlockBuilder blockBuilder, String property, String value) {
blockBuilder.addLine("response.getHeader('$property') ${convertHeaderComparison(value)}")
}
@Override
protected void processHeaderElement(BlockBuilder blockBuilder, String property, Pattern value) {
blockBuilder.addLine("response.getHeader('$property') ${convertHeaderComparison(value)}")
}
@Override
protected void validateResponseCodeBlock(BlockBuilder bb) {
if (outputMessage) {
bb.addLine("""def response = accurestMessaging.receiveMessage('${outputMessage.sentTo}')""")
} else {
bb.addLine('noExceptionThrown()')
}
}
@Override
protected void validateResponseHeadersBlock(BlockBuilder bb) {
outputMessage.headers?.collect { Header header ->
processHeaderElement(bb, header.name, header.serverValue)
}
}
@Override
protected String getResponseAsString() {
return 'accurestObjectMapper.writeValueAsString(response.payload)'
}
@Override
protected String addCommentSignIfRequired(String baseString) {
return baseString
}
@Override
protected BlockBuilder addColonIfRequired(BlockBuilder blockBuilder) {
return blockBuilder
}
@Override
protected String getPropertyInListString(String property, Integer listIndex) {
"$property[$listIndex]" ?: ''
}
@Override
protected String convertUnicodeEscapesIfRequired(String json) {
return StringEscapeUtils.unescapeJavaScript(json)
}
@Override
protected String getParsedXmlResponseBodyString(String responseString) {
return "def responseBody = new XmlSlurper().parseText($responseString)"
}
@Override
protected String getSimpleResponseBodyString(String responseString) {
return "def responseBody = ($responseString)"
}
@Override
protected String getInputString() {
String request = 'def inputMessage = accurestMessaging.create('
if (inputMessage.messageBody) {
request = "${request}'''${bodyAsString}'''\n\t\t"
}
if (inputMessage.messageHeaders) {
request = "${request},[\n"
}
def headers = []
inputMessage.messageHeaders?.collect { Header header ->
headers << "\t\t\t${getHeaderString(header)}"
}
request = "${request}${headers.join(',\n')}"
if (inputMessage.messageHeaders) {
request = "${request}\n\t\t]"
}
return "${request})"
}
@Override
protected String getHeaderString(Header header) {
return "'${getTestSideValue(header.name)}': '${getTestSideValue(header.serverValue)}'"
}
@Override
protected String getBodyString(String bodyAsString) {
return ''
}
@Override
protected String getMultipartFileParameterContent(String propertyName, NamedProperty propertyValue) {
return ''
}
@Override
protected String getParameterString(Map.Entry<String, Object> parameter) {
return ''
}
protected String convertHeaderComparison(String headerValue) {
return " == '$headerValue'"
}
protected String convertHeaderComparison(Pattern headerValue) {
return "==~ java.util.regex.Pattern.compile('$headerValue')"
}
}

View File

@@ -18,9 +18,9 @@ import static io.codearte.accurest.util.ContentUtils.getGroovyMultipartFileParam
*/
@PackageScope
@TypeChecked
abstract class SpockMethodBodyBuilder extends MethodBodyBuilder {
abstract class SpockMethodRequestProcessingBodyBuilder extends RequestProcessingMethodBodyBuilder {
SpockMethodBodyBuilder(GroovyDsl stubDefinition) {
SpockMethodRequestProcessingBodyBuilder(GroovyDsl stubDefinition) {
super(stubDefinition)
}
@@ -70,12 +70,12 @@ abstract class SpockMethodBodyBuilder extends MethodBodyBuilder {
}
@Override
protected String getResponseString(Request request) {
protected String getInputString(Request request) {
return 'def response = given().spec(request)'
}
@Override
protected String getRequestString() {
protected String getInputString() {
return 'def request = given()'
}

View File

@@ -74,4 +74,9 @@ class AccurestConfigProperties {
* You can then mention them in your packaging task to create jar with stubs
*/
File stubsOutputDir
/**
* Which version of Accurest Messaging Core to use
*/
String accurestMessagingCoreVersion = "+"
}

View File

@@ -3,6 +3,8 @@ package io.codearte.accurest.dsl
import groovy.transform.EqualsAndHashCode
import groovy.transform.ToString
import groovy.transform.TypeChecked
import io.codearte.accurest.dsl.internal.Input
import io.codearte.accurest.dsl.internal.OutputMessage
import io.codearte.accurest.dsl.internal.Request
import io.codearte.accurest.dsl.internal.Response
@@ -14,6 +16,9 @@ class GroovyDsl {
Integer priority
Request request
Response response
String label
Input inputMessage
OutputMessage outputMessage
static GroovyDsl make(Closure closure) {
GroovyDsl dsl = new GroovyDsl()
@@ -26,6 +31,10 @@ class GroovyDsl {
this.priority = priority
}
void label(String label) {
this.label = label
}
void request(@DelegatesTo(Request) Closure closure) {
this.request = new Request()
closure.delegate = request
@@ -38,4 +47,16 @@ class GroovyDsl {
closure()
}
void input(@DelegatesTo(Input) Closure closure) {
this.inputMessage = new Input()
closure.delegate = inputMessage
closure()
}
void outputMessage(@DelegatesTo(OutputMessage) Closure closure) {
this.outputMessage = new OutputMessage()
closure.delegate = outputMessage
closure()
}
}

View File

@@ -40,6 +40,9 @@ class WireMockRequestStubStrategy extends BaseWireMockStubStrategy {
@PackageScope
RequestPattern buildClientRequestContent() {
if(!request) {
return null
}
RequestPattern requestPattern = new RequestPattern()
appendMethod(requestPattern)
appendHeaders(requestPattern)

View File

@@ -27,6 +27,9 @@ class WireMockResponseStubStrategy extends BaseWireMockStubStrategy {
@PackageScope
ResponseDefinition buildClientResponseContent() {
if(!response) {
return null
}
ResponseDefinitionBuilder builder = new ResponseDefinitionBuilder()
.withStatus(response.status.clientValue as Integer)
appendHeaders(builder)

View File

@@ -29,14 +29,20 @@ class WireMockStubStrategy {
@CompileDynamic
String toWireMockClientStub() {
StubMapping stubMapping = new StubMapping()
RequestPattern request = wireMockRequestStubStrategy.buildClientRequestContent()
ResponseDefinition response = wireMockResponseStubStrategy.buildClientResponseContent()
if (priority) {
stubMapping.priority = priority
}
stubMapping.request = request
stubMapping.response = response
if (!request || !response) {
return ''
}
if (contract.order != null) {
stubMapping.scenarioName = "Scenario_" + rootName
stubMapping.requiredScenarioState = contract.order == 0 ? STEP_START : STEP_PREFIX + contract.order

View File

@@ -0,0 +1,77 @@
package io.codearte.accurest.dsl.internal
import groovy.transform.CompileStatic
import groovy.transform.EqualsAndHashCode
import groovy.transform.ToString
import groovy.transform.TypeChecked
@TypeChecked
@EqualsAndHashCode
@ToString(includePackage = false, includeNames = true)
class Input extends Common {
String messageFrom
ExecutionProperty triggeredBy
Headers messageHeaders
BodyType messageBody
ExecutionProperty assertThat
Input() {}
Input(Input input) {
this.messageFrom = input.messageFrom
this.messageHeaders = input.messageHeaders
this.messageBody = input.messageBody
}
void messageFrom(String messageFrom) {
this.messageFrom = messageFrom
}
void triggeredBy(String triggeredBy) {
this.triggeredBy = new ExecutionProperty(triggeredBy)
}
BodyType messageBody(Object bodyAsValue) {
this.messageBody = new BodyType(bodyAsValue)
}
void messageHeaders(@DelegatesTo(Headers) Closure closure) {
this.messageHeaders = new Headers()
closure.delegate = messageHeaders
closure()
}
public static class BodyType extends DslProperty {
BodyType(Object clientValue, Object serverValue) {
super(clientValue, serverValue)
}
BodyType(Object singleValue) {
super(singleValue)
}
}
void assertThat(String assertThat) {
this.assertThat = new ExecutionProperty(assertThat)
}
}
@CompileStatic
@EqualsAndHashCode
@ToString(includePackage = false)
class ServerInput extends Input {
ServerInput(Input request) {
super(request)
}
}
@CompileStatic
@EqualsAndHashCode
@ToString(includePackage = false)
class ClientInput extends Input {
ClientInput(Input request) {
super(request)
}
}

View File

@@ -0,0 +1,65 @@
package io.codearte.accurest.dsl.internal
import groovy.transform.CompileStatic
import groovy.transform.EqualsAndHashCode
import groovy.transform.ToString
import groovy.transform.TypeChecked
@TypeChecked
@EqualsAndHashCode
@ToString(includePackage = false, includeNames = true)
class OutputMessage extends Common {
String sentTo
Headers headers
DslProperty body
ExecutionProperty assertThat
OutputMessage() {}
OutputMessage(OutputMessage outputMessage) {
this.sentTo = outputMessage.sentTo
this.headers = outputMessage.headers
this.body = outputMessage.body
}
void sentTo(String sentTo) {
this.sentTo = sentTo
}
void body(Object bodyAsValue) {
this.body = new DslProperty(bodyAsValue)
}
void body(DslProperty bodyAsValue) {
this.body = bodyAsValue
}
void headers(@DelegatesTo(Headers) Closure closure) {
this.headers = new Headers()
closure.delegate = headers
closure()
}
void assertThat(String assertThat) {
this.assertThat = new ExecutionProperty(assertThat)
}
}
@CompileStatic
@EqualsAndHashCode
@ToString(includePackage = false)
class ServerOutputMessage extends OutputMessage {
ServerOutputMessage(OutputMessage request) {
super(request)
}
}
@CompileStatic
@EqualsAndHashCode
@ToString(includePackage = false)
class ClientOutputMessage extends OutputMessage {
ClientOutputMessage(OutputMessage request) {
super(request)
}
}

View File

@@ -287,6 +287,15 @@ class ContentUtils {
return ContentType.JSON
}
public static ContentType recognizeContentTypeFromContent(String string) {
try {
new JsonSlurper().parseText(string)
return ContentType.JSON
} catch (Exception e){
return ContentType.UNKNOWN
}
}
public static ContentType recognizeContentTypeFromContent(Object gstring) {
return ContentType.UNKNOWN
}

View File

@@ -0,0 +1,14 @@
package io.codearte.accurest.builder
import com.fasterxml.jackson.annotation.JsonCreator
import groovy.transform.CompileStatic
@CompileStatic
class BookReturned implements Serializable {
final String bookName
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
BookReturned(String bookName) {
this.bookName = bookName
}
}

View File

@@ -37,7 +37,7 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub
stubMappingIsValidWireMockStub(contractDsl)
where:
methodBuilderName | methodBuilder
"JaxRsClientSpockMethodBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientSpockMethodBodyBuilder(dsl) }
"JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl) }
"JaxRsClientJUnitMethodBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl) }
}
@@ -71,7 +71,7 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub
stubMappingIsValidWireMockStub(new WireMockStubStrategy("Test", new Contract(null, false, 0, null), contractDsl).toWireMockClientStub())
where:
methodBuilderName | methodBuilder
"JaxRsClientSpockMethodBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientSpockMethodBodyBuilder(dsl) }
"JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl) }
"JaxRsClientJUnitMethodBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl) }
}
@@ -107,7 +107,7 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub
stubMappingIsValidWireMockStub(new WireMockStubStrategy("Test", new Contract(null, false, 0, null), contractDsl).toWireMockClientStub())
where:
methodBuilderName | methodBuilder
"JaxRsClientSpockMethodBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientSpockMethodBodyBuilder(dsl) }
"JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl) }
"JaxRsClientJUnitMethodBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl) }
}
@@ -136,9 +136,9 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub
and:
stubMappingIsValidWireMockStub(contractDsl)
where:
methodBuilderName | methodBuilder | bodyString
"JaxRsClientSpockMethodBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientSpockMethodBodyBuilder(dsl) } | """entity('{\"items\":[\"HOP\"]}', 'application/json')"""
"JaxRsClientJUnitMethodBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl) } | 'entity("{\\"items\\":[\\"HOP\\"]}", "application/json")'
methodBuilderName | methodBuilder | bodyString
"JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl) } | """entity('{\"items\":[\"HOP\"]}', 'application/json')"""
"JaxRsClientJUnitMethodBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl) } | 'entity("{\\"items\\":[\\"HOP\\"]}", "application/json")'
}
@Issue("#88")
@@ -166,9 +166,9 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub
and:
stubMappingIsValidWireMockStub(contractDsl)
where:
methodBuilderName | methodBuilder | bodyString
"JaxRsClientSpockMethodBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientSpockMethodBodyBuilder(dsl) } | """entity('property1=VAL1', 'application/octet-stream')"""
"JaxRsClientJUnitMethodBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl) } | 'entity("\\"property1=VAL1\\"", "application/octet-stream")'
methodBuilderName | methodBuilder | bodyString
"JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl) } | """entity('property1=VAL1', 'application/octet-stream')"""
"JaxRsClientJUnitMethodBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl) } | 'entity("\\"property1=VAL1\\"", "application/octet-stream")'
}
@Unroll
@@ -201,7 +201,7 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub
stubMappingIsValidWireMockStub(contractDsl)
where:
methodBuilderName | methodBuilder
"JaxRsClientSpockMethodBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientSpockMethodBodyBuilder(dsl) }
"JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl) }
"JaxRsClientJUnitMethodBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl) }
}
@@ -234,7 +234,7 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub
stubMappingIsValidWireMockStub(contractDsl)
where:
methodBuilderName | methodBuilder
"JaxRsClientSpockMethodBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientSpockMethodBodyBuilder(dsl) }
"JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl) }
"JaxRsClientJUnitMethodBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl) }
}
@@ -267,7 +267,7 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub
stubMappingIsValidWireMockStub(contractDsl)
where:
methodBuilderName | methodBuilder
"JaxRsClientSpockMethodBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientSpockMethodBodyBuilder(dsl) }
"JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl) }
"JaxRsClientJUnitMethodBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl) }
}
@@ -306,7 +306,7 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub
stubMappingIsValidWireMockStub(contractDsl)
where:
methodBuilderName | methodBuilder
"JaxRsClientSpockMethodBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientSpockMethodBodyBuilder(dsl) }
"JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl) }
"JaxRsClientJUnitMethodBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl) }
}
@@ -339,7 +339,7 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub
stubMappingIsValidWireMockStub(contractDsl)
where:
methodBuilderName | methodBuilder
"JaxRsClientSpockMethodBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientSpockMethodBodyBuilder(dsl) }
"JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl) }
"JaxRsClientJUnitMethodBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl) }
}
@@ -367,9 +367,9 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub
and:
stubMappingIsValidWireMockStub(contractDsl)
where:
methodBuilderName | methodBuilder | requestString
"JaxRsClientSpockMethodBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientSpockMethodBodyBuilder(dsl) } | "request('text/plain')"
"JaxRsClientJUnitMethodBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl) } | 'request("text/plain")'
methodBuilderName | methodBuilder | requestString
"JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl) } | "request('text/plain')"
"JaxRsClientJUnitMethodBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl) } | 'request("text/plain")'
}
@Unroll
@@ -401,9 +401,9 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub
and:
stubMappingIsValidWireMockStub(contractDsl)
where:
methodBuilderName | methodBuilder | requestStrings
"JaxRsClientSpockMethodBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientSpockMethodBodyBuilder(dsl) } | ["""entity('', 'text/plain')""", """header('Timer', '123')"""]
"JaxRsClientJUnitMethodBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl) } | ['entity("\\"\\"", "text/plain")', 'header("Timer", "123")']
methodBuilderName | methodBuilder | requestStrings
"JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl) } | ["""entity('', 'text/plain')""", """header('Timer', '123')"""]
"JaxRsClientJUnitMethodBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl) } | ['entity("\\"\\"", "text/plain")', 'header("Timer", "123")']
}
@Unroll
@@ -456,9 +456,9 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub
and:
stubMappingIsValidWireMockStub(contractDsl)
where:
methodBuilderName | methodBuilder | modifyStringIfRequired
"JaxRsClientSpockMethodBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientSpockMethodBodyBuilder(dsl) } | { String paramString -> paramString }
"JaxRsClientJUnitMethodBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl) } | { String paramString -> paramString.replace("'", "\"") }
methodBuilderName | methodBuilder | modifyStringIfRequired
"JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl) } | { String paramString -> paramString }
"JaxRsClientJUnitMethodBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl) } | { String paramString -> paramString.replace("'", "\"") }
}
@Issue('#169')
@@ -512,9 +512,9 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub
and:
stubMappingIsValidWireMockStub(contractDsl)
where:
methodBuilderName | methodBuilder | modifyStringIfRequired
"JaxRsClientSpockMethodBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientSpockMethodBodyBuilder(dsl) } | { String paramString -> paramString }
"JaxRsClientJUnitMethodBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl) } | { String paramString -> paramString.replace("'", "\"") }
methodBuilderName | methodBuilder | modifyStringIfRequired
"JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl) } | { String paramString -> paramString }
"JaxRsClientJUnitMethodBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl) } | { String paramString -> paramString.replace("'", "\"") }
}
@Unroll
@@ -541,9 +541,9 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub
and:
stubMappingIsValidWireMockStub(contractDsl)
where:
methodBuilderName | methodBuilder | bodyString
"JaxRsClientSpockMethodBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientSpockMethodBodyBuilder(dsl) } | "entity('', 'application/octet-stream')"
"JaxRsClientJUnitMethodBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl) } | 'entity("\\"\\"", "application/octet-stream"'
methodBuilderName | methodBuilder | bodyString
"JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl) } | "entity('', 'application/octet-stream')"
"JaxRsClientJUnitMethodBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl) } | 'entity("\\"\\"", "application/octet-stream"'
}
@Unroll
@@ -570,9 +570,9 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub
and:
stubMappingIsValidWireMockStub(contractDsl)
where:
methodBuilderName | methodBuilder | bodyDefinitionString | bodyEvaluationString
"JaxRsClientSpockMethodBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientSpockMethodBodyBuilder(dsl) } | "String responseAsString = response.readEntity(String)" | 'responseBody == "test"'
"JaxRsClientJUnitMethodBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl) } | 'Object responseBody = (responseAsString);' | 'assertThat(responseBody).isEqualTo("test");'
methodBuilderName | methodBuilder | bodyDefinitionString | bodyEvaluationString
"JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl) } | "String responseAsString = response.readEntity(String)" | 'responseBody == "test"'
"JaxRsClientJUnitMethodBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl) } | 'Object responseBody = (responseAsString);' | 'assertThat(responseBody).isEqualTo("test");'
}
@Issue('#171')
@@ -604,9 +604,9 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub
and:
stubMappingIsValidWireMockStub(contractDsl)
where:
methodBuilderName | methodBuilder | methodString
"JaxRsClientSpockMethodBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientSpockMethodBodyBuilder(dsl) } | ".method('GET')"
"JaxRsClientJUnitMethodBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl) } | 'method("GET")'
methodBuilderName | methodBuilder | methodString
"JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl) } | ".method('GET')"
"JaxRsClientJUnitMethodBodyBuilder" | { GroovyDsl dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl) } | 'method("GET")'
}
}

View File

@@ -0,0 +1,252 @@
package io.codearte.accurest.builder
import io.codearte.accurest.dsl.GroovyDsl
import spock.lang.Specification
/**
* @author Marcin Grzejszczak
*/
class MessagingMethodBodyBuilderSpec extends Specification {
def "should work for triggered based messaging with Spock"() {
given:
def contractDsl = GroovyDsl.make {
label 'some_label'
input {
triggeredBy('bookReturnedTriggered()')
}
outputMessage {
sentTo('activemq:output')
body('''{ "bookName" : "foo" }''')
headers {
header('BOOK-NAME', 'foo')
}
}
}
MethodBodyBuilder builder = new SpockMessagingMethodBodyBuilder(contractDsl)
BlockBuilder blockBuilder = new BlockBuilder(" ")
when:
builder.appendTo(blockBuilder)
def test = blockBuilder.toString()
then:
stripped(test) == stripped('''
when:
bookReturnedTriggered()
then:
def response = accurestMessaging.receiveMessage('activemq:output')
response.getHeader('BOOK-NAME') == 'foo'
and:
DocumentContext parsedJson = JsonPath.parse(accurestObjectMapper.writeValueAsString(response.payload))
assertThatJson(parsedJson).field("bookName").isEqualTo("foo")
''')
}
def "should work for triggered based messaging with JUnit"() {
given:
def contractDsl = GroovyDsl.make {
label 'some_label'
input {
triggeredBy('bookReturnedTriggered()')
}
outputMessage {
sentTo('activemq:output')
body('''{ "bookName" : "foo" }''')
headers {
header('BOOK-NAME', 'foo')
}
}
}
MethodBodyBuilder builder = new JUnitMessagingMethodBodyBuilder(contractDsl)
BlockBuilder blockBuilder = new BlockBuilder(" ")
when:
builder.appendTo(blockBuilder)
def test = blockBuilder.toString()
then:
stripped(test) == stripped('''
// when:
bookReturnedTriggered();
// then:
AccurestMessage response = accurestMessaging.receiveMessage("activemq:output");
assertThat(response.getHeader("BOOK-NAME")).isEqualTo("foo");
// and:
DocumentContext parsedJson = JsonPath.parse(accurestObjectMapper.writeValueAsString(response.getPayload()));
assertThatJson(parsedJson).field("bookName").isEqualTo("foo");
''')
}
private String stripped(String text) {
return text.stripIndent().stripMargin().replace('\t', '').replace('\n', '')
}
def "should generate tests triggered by a message for Spock"() {
given:
def contractDsl = GroovyDsl.make {
label 'some_label'
input {
messageFrom('jms:input')
messageBody([
bookName: 'foo'
])
messageHeaders {
header('sample', 'header')
}
}
outputMessage {
sentTo('jms:output')
body([
bookName: 'foo'
])
headers {
header('BOOK-NAME', 'foo')
}
}
}
MethodBodyBuilder builder = new SpockMessagingMethodBodyBuilder(contractDsl)
BlockBuilder blockBuilder = new BlockBuilder(" ")
when:
builder.appendTo(blockBuilder)
def test = blockBuilder.toString()
then:
stripped(test) == stripped('''
given:
def inputMessage = accurestMessaging.create(
\'\'\'{"bookName":"foo"}\'\'\',
['sample': 'header']
)
when:
accurestMessaging.send(inputMessage, 'jms:input')
then:
def response = accurestMessaging.receiveMessage('jms:output')
response.getHeader('BOOK-NAME') == 'foo'
and:
DocumentContext parsedJson = JsonPath.parse(accurestObjectMapper.writeValueAsString(response.payload))
assertThatJson(parsedJson).field("bookName").isEqualTo("foo")
''')
}
def "should generate tests triggered by a message for JUnit"() {
given:
def contractDsl = GroovyDsl.make {
label 'some_label'
input {
messageFrom('jms:input')
messageBody([
bookName: 'foo'
])
messageHeaders {
header('sample', 'header')
}
}
outputMessage {
sentTo('jms:output')
body([
bookName: 'foo'
])
headers {
header('BOOK-NAME', 'foo')
}
}
}
MethodBodyBuilder builder = new JUnitMessagingMethodBodyBuilder(contractDsl)
BlockBuilder blockBuilder = new BlockBuilder(" ")
when:
builder.appendTo(blockBuilder)
def test = blockBuilder.toString()
then:
stripped(test) == stripped('''
// given:
AccurestMessage inputMessage = accurestMessaging.create(
"{\\"bookName\\":\\"foo\\"}"
, headers()
.header("sample", "header"));
// when:
accurestMessaging.send(inputMessage, "jms:input");
// then:
AccurestMessage response = accurestMessaging.receiveMessage("jms:output");
assertThat(response.getHeader("BOOK-NAME")).isEqualTo("foo");
// and:
DocumentContext parsedJson = JsonPath.parse(accurestObjectMapper.writeValueAsString(response.getPayload()));
assertThatJson(parsedJson).field("bookName").isEqualTo("foo");
''')
}
def "should generate tests without destination, triggered by a message"() {
given:
def contractDsl = GroovyDsl.make {
label 'some_label'
input {
messageFrom('jms:delete')
messageBody([
bookName: 'foo'
])
messageHeaders {
header('sample', 'header')
}
assertThat('bookWasDeleted()')
}
}
MethodBodyBuilder builder = new SpockMessagingMethodBodyBuilder(contractDsl)
BlockBuilder blockBuilder = new BlockBuilder(" ")
when:
builder.appendTo(blockBuilder)
def test = blockBuilder.toString()
then:
stripped(test) == stripped('''
given:
def inputMessage = accurestMessaging.create(
\'\'\'{"bookName":"foo"}\'\'\',
['sample': 'header']
)
when:
accurestMessaging.send(inputMessage, 'jms:delete')
then:
noExceptionThrown()
bookWasDeleted()
''')
}
def "should generate tests without destination, triggered by a message for JUnit"() {
given:
def contractDsl = GroovyDsl.make {
label 'some_label'
input {
messageFrom('jms:delete')
messageBody([
bookName: 'foo'
])
messageHeaders {
header('sample', 'header')
}
assertThat('bookWasDeleted()')
}
}
MethodBodyBuilder builder = new JUnitMessagingMethodBodyBuilder(contractDsl)
BlockBuilder blockBuilder = new BlockBuilder(" ")
when:
builder.appendTo(blockBuilder)
def test = blockBuilder.toString()
then:
stripped(test) == stripped('''
// given:
AccurestMessage inputMessage = accurestMessaging.create(
"{\\"bookName\\":\\"foo\\"}"
, headers()
.header("sample", "header"));
// when:
accurestMessaging.send(inputMessage, "jms:delete");
// then:
bookWasDeleted();
''')
}
}

View File

@@ -0,0 +1,137 @@
package io.codearte.accurest.builder
import io.codearte.accurest.dsl.GroovyDsl
import spock.lang.Specification
/**
# TO CONSIDER
- multiple messages can be sent out (for now let's focus on a single one)
- tests thanks to stream-test-binder will get executed in single threaded mode (no need for awaitility)
- do we need an explicit assertion of an input message (the one that enters the source?) or will
it be done in the processor
- let's support only JSON payload and headers taken from message ATM
# TRIGGERING MESSAGES
Triggering for the client side might be done via stub runner messaging module.
## JUNIT
@ClassRule public static AccurestRule stubFinder = new AccurestRule()
.repoRoot(repoRoot())
.downloadStub("io.codearte.accurest.stubs", "loanIssuance")
.downloadStub("io.codearte.accurest.stubs:fraudDetectionServer");
## SPRING
@Autowired StubFinder stubFinder
## TRIGGERING EXAMPLES
//test:
// execute all triggers for all artifacts
stubFinder.trigger()
// execute all triggers named 'some_label' for all artifacts
stubFinder.trigger("some_label")
// execute all triggers named 'some_label' for the artifact in Ivy notation
stubFinder.trigger("io.codearte.accurest.stubs:fraudDetectionServer", "some_label")
// execute all triggers named 'some_label' for the artifact with id ...
stubFinder.trigger("fraudDetectionServer", "some_label")
if no label is provided then all triggers will get executed
# CLIENT SIDE TEST EXAMPLE
## DSL
GroovyDsl.make {
label 'some_label'
input {
triggeredBy(execute('method()'))
}
outputMessage {
onChannel('messageFrom')
messageBody("book returned")
}
}
## TEST
@Test
public void run_some_test() {
// given
client.borrowABook();
// when - sends a message to the messageFrom provided in the "outputMessage" section of the DSL
stubFinder.trigger("client_returned_a_book");
// then
then(client).hasNoBooksBorrowed();
}
*
* @author Marcin Grzejszczak
*/
class MessagingSpec extends Specification {
// client side: must have a possibility to "trigger" sending of a message to the given messageFrom
// server side: will run the method and await upon receiving message on the output messageFrom
def "should generate tests triggered by a method"() {
expect:
GroovyDsl.make {
label 'some_label'
input {
triggeredBy('bookReturnedTriggered()')
}
outputMessage {
sentTo('channel')
body('''{ "bookName" : "foo" }''')
headers {
header('BOOK-NAME', 'foo')
}
}
}
}
// client side: if sends a message to input.messageFrom then message will be sent to output.messageFrom
// server side: will send a message to input, verify the message contents and await upon receiving message on the output messageFrom
def "should generate tests triggered by a message"() {
expect:
GroovyDsl.make {
input {
messageFrom('input')
messageBody("some message")
messageHeaders {
header('key', 'value')
}
}
outputMessage {
sentTo('output')
body('message')
headers {
header('anotherkey', 'anothervalue')
}
}
}
}
// client side: if sends a message to input.messageFrom then message if matches will get consumed
// server side: will send a message to input and verify the message contents
def "should generate tests without destination, triggered by a message"() {
expect:
GroovyDsl.make {
input {
messageFrom('input')
messageBody("some message")
messageHeaders {
header('key', 'value')
}
}
}
}
}

View File

@@ -100,7 +100,7 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub
stubMappingIsValidWireMockStub(contractDsl)
where:
methodBuilderName | methodBuilder
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodBodyBuilder(dsl) }
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl) }
"MockMvcJUnitMethodBuilder" | { GroovyDsl dsl -> new MockMvcJUnitMethodBodyBuilder(dsl) }
}
@@ -134,7 +134,7 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub
stubMappingIsValidWireMockStub(contractDsl)
where:
methodBuilderName | methodBuilder
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodBodyBuilder(dsl) }
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl) }
"MockMvcJUnitMethodBuilder" | { GroovyDsl dsl -> new MockMvcJUnitMethodBodyBuilder(dsl) }
}
@@ -170,7 +170,7 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub
stubMappingIsValidWireMockStub(contractDsl)
where:
methodBuilderName | methodBuilder
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodBodyBuilder(dsl) }
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl) }
"MockMvcJUnitMethodBuilder" | { GroovyDsl dsl -> new MockMvcJUnitMethodBodyBuilder(dsl) }
}
@@ -199,9 +199,9 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub
and:
stubMappingIsValidWireMockStub(contractDsl)
where:
methodBuilderName | methodBuilder | bodyString
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodBodyBuilder(dsl) } | """.body('''{\"items\":[\"HOP\"]}''')"""
"MockMvcJUnitMethodBuilder" | { GroovyDsl dsl -> new MockMvcJUnitMethodBodyBuilder(dsl) } | '.body("{\\"items\\":[\\"HOP\\"]}")'
methodBuilderName | methodBuilder | bodyString
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl) } | """.body('''{\"items\":[\"HOP\"]}''')"""
"MockMvcJUnitMethodBuilder" | { GroovyDsl dsl -> new MockMvcJUnitMethodBodyBuilder(dsl) } | '.body("{\\"items\\":[\\"HOP\\"]}")'
}
@Issue("#88")
@@ -229,9 +229,9 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub
and:
stubMappingIsValidWireMockStub(contractDsl)
where:
methodBuilderName | methodBuilder | bodyString
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodBodyBuilder(dsl) } | """.body('''property1=VAL1''')"""
"MockMvcJUnitMethodBuilder" | { GroovyDsl dsl -> new MockMvcJUnitMethodBodyBuilder(dsl) } | '.body("\\"property1=VAL1\\"")'
methodBuilderName | methodBuilder | bodyString
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl) } | """.body('''property1=VAL1''')"""
"MockMvcJUnitMethodBuilder" | { GroovyDsl dsl -> new MockMvcJUnitMethodBodyBuilder(dsl) } | '.body("\\"property1=VAL1\\"")'
}
@Issue("185")
@@ -264,7 +264,7 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub
stubMappingIsValidWireMockStub(contractDsl)
where:
methodBuilderName | methodBuilder
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodBodyBuilder(dsl) }
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl) }
"MockMvcJUnitMethodBuilder" | { GroovyDsl dsl -> new MockMvcJUnitMethodBodyBuilder(dsl) }
}
@@ -298,7 +298,7 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub
stubMappingIsValidWireMockStub(contractDsl)
where:
methodBuilderName | methodBuilder
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodBodyBuilder(dsl) }
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl) }
"MockMvcJUnitMethodBuilder" | { GroovyDsl dsl -> new MockMvcJUnitMethodBodyBuilder(dsl) }
}
@@ -331,7 +331,7 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub
stubMappingIsValidWireMockStub(contractDsl)
where:
methodBuilderName | methodBuilder
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodBodyBuilder(dsl) }
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl) }
"MockMvcJUnitMethodBuilder" | { GroovyDsl dsl -> new MockMvcJUnitMethodBodyBuilder(dsl) }
}
@@ -364,7 +364,7 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub
stubMappingIsValidWireMockStub(contractDsl)
where:
methodBuilderName | methodBuilder
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodBodyBuilder(dsl) }
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl) }
"MockMvcJUnitMethodBuilder" | { GroovyDsl dsl -> new MockMvcJUnitMethodBodyBuilder(dsl) }
}
@@ -401,7 +401,7 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub
stubMappingIsValidWireMockStub(contractDsl)
where:
methodBuilderName | methodBuilder
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodBodyBuilder(dsl) }
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl) }
"MockMvcJUnitMethodBuilder" | { GroovyDsl dsl -> new MockMvcJUnitMethodBodyBuilder(dsl) }
}
@@ -432,7 +432,7 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub
stubMappingIsValidWireMockStub(contractDsl)
where:
methodBuilderName | methodBuilder
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodBodyBuilder(dsl) }
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl) }
"MockMvcJUnitMethodBuilder" | { GroovyDsl dsl -> new MockMvcJUnitMethodBodyBuilder(dsl) }
}
@@ -463,7 +463,7 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub
stubMappingIsValidWireMockStub(contractDsl)
where:
methodBuilderName | methodBuilder
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodBodyBuilder(dsl) }
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl) }
"MockMvcJUnitMethodBuilder" | { GroovyDsl dsl -> new MockMvcJUnitMethodBodyBuilder(dsl) }
}
@@ -511,7 +511,7 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub
stubMappingIsValidWireMockStub(contractDsl)
where:
methodBuilderName | methodBuilder
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodBodyBuilder(dsl) }
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl) }
"MockMvcJUnitMethodBuilder" | { GroovyDsl dsl -> new MockMvcJUnitMethodBodyBuilder(dsl) }
}
@@ -560,7 +560,7 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub
stubMappingIsValidWireMockStub(contractDsl)
where:
methodBuilderName | methodBuilder
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodBodyBuilder(dsl) }
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl) }
"MockMvcJUnitMethodBuilder" | { GroovyDsl dsl -> new MockMvcJUnitMethodBodyBuilder(dsl) }
}
@@ -587,9 +587,9 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub
and:
stubMappingIsValidWireMockStub(contractDsl)
where:
methodBuilderName | methodBuilder | bodyString
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodBodyBuilder(dsl) } | ".body('''''')"
"MockMvcJUnitMethodBuilder" | { GroovyDsl dsl -> new MockMvcJUnitMethodBodyBuilder(dsl) } | ".body(\"\\\"\\\"\")"
methodBuilderName | methodBuilder | bodyString
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl) } | ".body('''''')"
"MockMvcJUnitMethodBuilder" | { GroovyDsl dsl -> new MockMvcJUnitMethodBodyBuilder(dsl) } | ".body(\"\\\"\\\"\")"
}
@Unroll
@@ -616,9 +616,9 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub
and:
stubMappingIsValidWireMockStub(contractDsl)
where:
methodBuilderName | methodBuilder | bodyDefinitionString | bodyEvaluationString
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodBodyBuilder(dsl) } | 'def responseBody = (response.body.asString())' | 'responseBody == "test"'
"MockMvcJUnitMethodBuilder" | { GroovyDsl dsl -> new MockMvcJUnitMethodBodyBuilder(dsl) } | 'Object responseBody = (response.getBody().asString());' | 'assertThat(responseBody).isEqualTo("test");'
methodBuilderName | methodBuilder | bodyDefinitionString | bodyEvaluationString
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl) } | 'def responseBody = (response.body.asString())' | 'responseBody == "test"'
"MockMvcJUnitMethodBuilder" | { GroovyDsl dsl -> new MockMvcJUnitMethodBodyBuilder(dsl) } | 'Object responseBody = (response.getBody().asString());' | 'assertThat(responseBody).isEqualTo("test");'
}
@Issue('113')
@@ -656,9 +656,9 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub
and:
stubMappingIsValidWireMockStub(contractDsl)
where:
methodBuilderName | methodBuilder | headerEvaluationString
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodBodyBuilder(dsl) } | '''response.header('Location') ==~ java.util.regex.Pattern.compile('http://localhost/partners/[0-9]+/users/[0-9]+')'''
"MockMvcJUnitMethodBuilder" | { GroovyDsl dsl -> new MockMvcJUnitMethodBodyBuilder(dsl) } | 'assertThat(response.header("Location")).matches("http://localhost/partners/[0-9]+/users/[0-9]+");'
methodBuilderName | methodBuilder | headerEvaluationString
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl) } | '''response.header('Location') ==~ java.util.regex.Pattern.compile('http://localhost/partners/[0-9]+/users/[0-9]+')'''
"MockMvcJUnitMethodBuilder" | { GroovyDsl dsl -> new MockMvcJUnitMethodBodyBuilder(dsl) } | 'assertThat(response.header("Location")).matches("http://localhost/partners/[0-9]+/users/[0-9]+");'
}
@Issue('115')
@@ -696,9 +696,9 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub
and:
stubMappingIsValidWireMockStub(contractDsl)
where:
methodBuilderName | methodBuilder | headerEvaluationString
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodBodyBuilder(dsl) } | '''response.header('Location') ==~ java.util.regex.Pattern.compile('^((http[s]?|ftp):\\/)\\/?([^:\\/\\s]+)(:[0-9]{1,5})?/partners/[0-9]+/users/[0-9]+')'''
"MockMvcJUnitMethodBuilder" | { GroovyDsl dsl -> new MockMvcJUnitMethodBodyBuilder(dsl) } | 'assertThat(response.header("Location")).matches("^((http[s]?|ftp):/)/?([^:/s]+)(:[0-9]{1,5})?/partners/[0-9]+/users/[0-9]+");'
methodBuilderName | methodBuilder | headerEvaluationString
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl) } | '''response.header('Location') ==~ java.util.regex.Pattern.compile('^((http[s]?|ftp):\\/)\\/?([^:\\/\\s]+)(:[0-9]{1,5})?/partners/[0-9]+/users/[0-9]+')'''
"MockMvcJUnitMethodBuilder" | { GroovyDsl dsl -> new MockMvcJUnitMethodBodyBuilder(dsl) } | 'assertThat(response.header("Location")).matches("^((http[s]?|ftp):/)/?([^:/s]+)(:[0-9]{1,5})?/partners/[0-9]+/users/[0-9]+");'
}
@Unroll
@@ -739,7 +739,7 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub
stubMappingIsValidWireMockStub(contractDsl)
where:
methodBuilderName | methodBuilder
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodBodyBuilder(dsl) }
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl) }
"MockMvcJUnitMethodBuilder" | { GroovyDsl dsl -> new MockMvcJUnitMethodBodyBuilder(dsl) }
}
@@ -773,7 +773,7 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub
stubMappingIsValidWireMockStub(contractDsl)
where:
methodBuilderName | methodBuilder
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodBodyBuilder(dsl) }
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl) }
"MockMvcJUnitMethodBuilder" | { GroovyDsl dsl -> new MockMvcJUnitMethodBodyBuilder(dsl) }
}
@@ -813,7 +813,7 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub
test.contains("""assertThatJson(parsedJson).field("message").matches("User not found by email = \\\\\\\\[[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\\\\\\\.[a-zA-Z]{2,4}\\\\\\\\]")""")
where:
methodBuilderName | methodBuilder
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodBodyBuilder(dsl) }
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl) }
"MockMvcJUnitMethodBuilder" | { GroovyDsl dsl -> new MockMvcJUnitMethodBodyBuilder(dsl) }
}
@@ -821,7 +821,7 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub
@Unroll
def "should not omit the optional field in the test creation with MockMvcSpockMethodBodyBuilder"() {
given:
MethodBodyBuilder builder = new MockMvcSpockMethodBodyBuilder(contractDsl)
MethodBodyBuilder builder = new MockMvcSpockMethodRequestProcessingBodyBuilder(contractDsl)
BlockBuilder blockBuilder = new BlockBuilder(" ")
when:
builder.appendTo(blockBuilder)
@@ -900,9 +900,9 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub
assert test.contains(assertionString)
}
where:
methodBuilderName | methodBuilder | assertionStrings
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodBodyBuilder(dsl) } | ['''assertThatRejectionReasonIsNull(parsedJson.read('$.rejectionReason'))''', '''assertThatLocationIsNull(response.header('Location'))''']
"MockMvcJUnitMethodBuilder" | { GroovyDsl dsl -> new MockMvcJUnitMethodBodyBuilder(dsl) } | ['''assertThatRejectionReasonIsNull(parsedJson.read("$.rejectionReason"))''', '''assertThatLocationIsNull(response.header("Location"))''']
methodBuilderName | methodBuilder | assertionStrings
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl) } | ['''assertThatRejectionReasonIsNull(parsedJson.read('$.rejectionReason'))''', '''assertThatLocationIsNull(response.header('Location'))''']
"MockMvcJUnitMethodBuilder" | { GroovyDsl dsl -> new MockMvcJUnitMethodBodyBuilder(dsl) } | ['''assertThatRejectionReasonIsNull(parsedJson.read("$.rejectionReason"))''', '''assertThatLocationIsNull(response.header("Location"))''']
}
@Unroll
@@ -968,9 +968,9 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub
!test.contains("clientValue")
!test.contains("cursor")
where:
methodBuilderName | methodBuilder | bodyString
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodBodyBuilder(dsl) } | '"street":"Light Street"'
"MockMvcJUnitMethodBuilder" | { GroovyDsl dsl -> new MockMvcJUnitMethodBodyBuilder(dsl) } | '\\"street\\":\\"Light Street\\"'
methodBuilderName | methodBuilder | bodyString
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl) } | '"street":"Light Street"'
"MockMvcJUnitMethodBuilder" | { GroovyDsl dsl -> new MockMvcJUnitMethodBodyBuilder(dsl) } | '\\"street\\":\\"Light Street\\"'
}
@@ -1009,7 +1009,7 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub
!test.contains("\\u041f")
where:
methodBuilderName | methodBuilder
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodBodyBuilder(dsl) }
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl) }
"MockMvcJUnitMethodBuilder" | { GroovyDsl dsl -> new MockMvcJUnitMethodBodyBuilder(dsl) }
}
@@ -1036,10 +1036,10 @@ World.''')
then:
test.contains(bodyString)
where:
methodBuilderName | methodBuilder | bodyString
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodBodyBuilder(dsl) } | """'''hello,
methodBuilderName | methodBuilder | bodyString
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl) } | """'''hello,
World.'''"""
"MockMvcJUnitMethodBuilder" | { GroovyDsl dsl -> new MockMvcJUnitMethodBodyBuilder(dsl) } | '\\"hello,\\nWorld.\\"'
"MockMvcJUnitMethodBuilder" | { GroovyDsl dsl -> new MockMvcJUnitMethodBodyBuilder(dsl) } | '\\"hello,\\nWorld.\\"'
}
@Issue('180')
@@ -1073,12 +1073,12 @@ World.'''"""
test.contains(requestString)
}
where:
methodBuilderName | methodBuilder | requestStrings
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodBodyBuilder(dsl) } | ["""'content-type', 'multipart/form-data;boundary=AaB03x'""",
""".param('formParameter', '"formParameterValue"'""",
""".param('someBooleanParameter', 'true')""",
""".multiPart('file', 'filename.csv', 'file content'.bytes)"""]
"MockMvcJUnitMethodBuilder" | { GroovyDsl dsl -> new MockMvcJUnitMethodBodyBuilder(dsl) } | ['"content-type", "multipart/form-data;boundary=AaB03x"',
methodBuilderName | methodBuilder | requestStrings
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl) } | ["""'content-type', 'multipart/form-data;boundary=AaB03x'""",
""".param('formParameter', '"formParameterValue"'""",
""".param('someBooleanParameter', 'true')""",
""".multiPart('file', 'filename.csv', 'file content'.bytes)"""]
"MockMvcJUnitMethodBuilder" | { GroovyDsl dsl -> new MockMvcJUnitMethodBodyBuilder(dsl) } | ['"content-type", "multipart/form-data;boundary=AaB03x"',
'.param("formParameter", "\\"formParameterValue\\"")',
'.param("someBooleanParameter", "true")',
'.multiPart("file", "filename.csv", "file content".getBytes());']
@@ -1113,7 +1113,7 @@ World.'''"""
test.contains('.multiPart')
where:
methodBuilderName | methodBuilder
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodBodyBuilder(dsl) }
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl) }
"MockMvcJUnitMethodBuilder" | { GroovyDsl dsl -> new MockMvcJUnitMethodBodyBuilder(dsl) }
}
@@ -1152,7 +1152,7 @@ World.'''"""
test.contains('''assertThatJson(parsedJson).array("authorities").matches("^[a-zA-Z0-9_\\\\- ]+\\$").value()''')
where:
methodBuilderName | methodBuilder
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodBodyBuilder(dsl) }
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl) }
"MockMvcJUnitMethodBuilder" | { GroovyDsl dsl -> new MockMvcJUnitMethodBodyBuilder(dsl) }
}
@@ -1183,7 +1183,7 @@ World.'''"""
test.contains('''assertThatRejectionReasonIsNull(''')
where:
methodBuilderName | methodBuilder
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodBodyBuilder(dsl) }
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl) }
"MockMvcJUnitMethodBuilder" | { GroovyDsl dsl -> new MockMvcJUnitMethodBodyBuilder(dsl) }
}

View File

@@ -31,6 +31,7 @@ class AccurestGradlePlugin implements Plugin<Project> {
project.dependencies.add("testCompile", "com.github.tomakehurst:wiremock:2.0.5-beta")
project.dependencies.add("testCompile", "com.toomuchcoding.jsonassert:jsonassert:${extension.getJsonAssertVersion()}")
project.dependencies.add("testCompile", "org.assertj:assertj-core:2.3.0")
project.dependencies.add("testCompile", "io.codearte.accurest:accurest-messaging-core:${extension.getAccurestMessagingCoreVersion()}")
project.afterEvaluate {
def hasIdea = project.plugins.findPlugin(IDEA_PLUGIN_CLASS)

View File

@@ -24,9 +24,13 @@ class AccurestIntegrationSpec extends IntegrationSpec {
}
protected void switchToJunitTestFramework() {
switchToJunitTestFramework(MVC_SPEC, MVC_TEST)
}
protected void switchToJunitTestFramework(String from, String to) {
Path path = buildFile.toPath()
String content = new StringBuilder(new String(Files.readAllBytes(path), UTF_8)).replaceAll(SPOCK, JUNIT)
.replaceAll(MVC_SPEC, MVC_TEST)
.replaceAll(from, to)
Files.write(path, content.getBytes(UTF_8))
}

View File

@@ -0,0 +1,29 @@
package io.codearte.accurest.plugin
import spock.lang.Stepwise
@Stepwise
class MessagingProjectSpec extends AccurestIntegrationSpec {
void setup() {
copyResources("functionalTest/messagingProject", "")
runTasksSuccessfully('clean') //delete accidental output when previously importing SimpleBoot into Idea to tweak it
}
def "should pass basic flow for Spock"() {
given:
assert fileExists('build.gradle')
expect:
runTasksSuccessfully('check')
}
def "should pass basic flow for JUnit"() {
given:
runTasksSuccessfully('clean')
assert fileExists('build.gradle')
expect:
switchToJunitTestFramework('io.codearte.accurest.samples.book.MessagingBaseSpec', 'io.codearte.accurest.samples.book.MessagingBaseTest')
runTasksSuccessfully('check')
}
}

View File

@@ -0,0 +1,105 @@
buildscript {
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
// will be passed via classpath
// classpath "io.codearte.accurest:accurest-gradle-plugin:+"
}
}
apply plugin: 'groovy'
apply plugin: 'accurest'
apply plugin: 'maven-publish'
ext {
contractsDir = file("${project.rootDir}/repository/mappings/")
stubsOutputDirRoot = file("${project.buildDir}/production/${project.name}-stubs/")
wireMockStubsOutputDir = new File(stubsOutputDirRoot, 'repository/mappings/')
contractsOutputDir = new File(stubsOutputDirRoot, 'repository/accurest/')
}
configurations {
all {
resolutionStrategy {
eachDependency { DependencyResolveDetails details ->
// To prevent an accidental usage of groovy-all.jar and groovy.jar in different versions
// all modularized Groovy jars are replaced with groovy-all.jar by default.
if (details.requested.group == 'org.codehaus.groovy' && details.requested.name != "groovy-all") {
details.useTarget("org.codehaus.groovy:groovy-all:${details.requested.version}")
}
}
}
}
}
repositories {
mavenCentral()
mavenLocal()
maven {
url "http://repo.spring.io/snapshot"
}
maven {
url "http://repo.spring.io/milestone"
}
}
dependencies {
compile "org.codehaus.groovy:groovy-all:2.4.5"
compile 'org.springframework.boot:spring-boot-starter-web:1.3.3.RELEASE'
compile 'org.springframework.boot:spring-boot-starter-actuator:1.3.3.RELEASE'
compile 'org.springframework.boot:spring-boot-starter-integration:1.3.3.RELEASE'
// will be passed via classpath (I have issues with doing that quite frankly)
compile 'io.codearte.accurest:accurest-messaging-integration:+'
testCompile "org.spockframework:spock-spring:1.0-groovy-2.4"
testCompile 'org.springframework.boot:spring-boot-starter-test:1.3.3.RELEASE'
testCompile "ch.qos.logback:logback-classic:1.1.2"
}
accurest {
//baseClassForTests = 'io.codearte.accurest.samples.book.MessagingBaseTest'
baseClassForTests = 'io.codearte.accurest.samples.book.MessagingBaseSpec'
basePackageForTests = 'accurest'
//targetFramework = 'JUnit'
targetFramework = 'Spock'
contractsDslDir = contractsDir
// generatedTestSourcesDir = file("${project.rootDir}/src/test/groovy/")
stubsOutputDir = wireMockStubsOutputDir
}
//TODO: Put it into the plugin
task createWireMockStubsOutputDir << {
wireMockStubsOutputDir.mkdirs()
}
generateWireMockClientStubs.dependsOn { createWireMockStubsOutputDir }
generateAccurest.dependsOn generateWireMockClientStubs
wrapper {
gradleVersion '2.12'
}
task copyContracts(type: Copy) {
from contractsDir
into contractsOutputDir
}
task stubsJar(type: Jar, dependsOn: ["generateWireMockClientStubs", copyContracts]) {
baseName = "${project.name}-stubs"
from stubsOutputDirRoot
}
artifacts {
archives stubsJar
}
publishing {
publications {
stubs(MavenPublication) {
artifactId "${project.name}-stubs"
artifact stubsJar
}
}
}

View File

@@ -0,0 +1,4 @@
groupId=io.codearte
jacksonMapper=1.9.13
restAssuredVersion=2.9.0
springVersion=4.2.3.RELEASE

View File

@@ -0,0 +1,6 @@
#Sun Apr 17 20:31:11 CEST 2016
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.12-bin.zip

View File

@@ -0,0 +1,160 @@
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"

View File

@@ -0,0 +1,90 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@@ -0,0 +1,13 @@
io.codearte.accurest.dsl.GroovyDsl.make {
label 'some_label'
input {
messageFrom('delete')
messageBody([
bookName: 'foo'
])
messageHeaders {
header('sample', 'header')
}
assertThat('bookWasDeleted()')
}
}

View File

@@ -0,0 +1,13 @@
io.codearte.accurest.dsl.GroovyDsl.make {
label 'some_label'
input {
triggeredBy('bookReturnedTriggered()')
}
outputMessage {
sentTo('output')
body('''{ "bookName" : "foo" }''')
headers {
header('BOOK-NAME', 'foo')
}
}
}

View File

@@ -0,0 +1,21 @@
io.codearte.accurest.dsl.GroovyDsl.make {
label 'some_label'
input {
messageFrom('input')
messageBody([
bookName: 'foo'
])
messageHeaders {
header('sample', 'header')
}
}
outputMessage {
sentTo('output')
body([
bookName: 'foo'
])
headers {
header('BOOK-NAME', 'foo')
}
}
}

View File

@@ -0,0 +1 @@
rootProject.name='bootSimple'

View File

@@ -0,0 +1,14 @@
package io.codearte.accurest.samples.book
import com.fasterxml.jackson.annotation.JsonCreator
import groovy.transform.CompileStatic
@CompileStatic
class BookDeleted {
final String bookName
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
BookDeleted(String bookName) {
this.bookName = bookName
}
}

View File

@@ -0,0 +1,38 @@
package io.codearte.accurest.samples.book
import groovy.transform.CompileStatic
import groovy.util.logging.Slf4j
import org.springframework.messaging.Message
import org.springframework.messaging.MessageHeaders
import org.springframework.messaging.support.MessageBuilder
import java.util.concurrent.atomic.AtomicBoolean
@CompileStatic
@Slf4j
class BookListener {
/**
Scenario for "should generate tests triggered by a message":
client side: if sends a message to input.messageFrom then message will be sent to output.messageFrom
server side: will send a message to input, verify the message contents and await upon receiving message on the output messageFrom
*/
Message returnBook(BookReturned bookReturned) {
log.info("Returning book [$bookReturned]")
return MessageBuilder.createMessage(bookReturned, new MessageHeaders([
'BOOK-NAME': bookReturned.bookName as Object
]))
}
/**
Scenario for "should generate tests triggered by a message":
client side: if sends a message to input.messageFrom then message will be sent to output.messageFrom
server side: will send a message to input, verify the message contents and await upon receiving message on the output messageFrom
*/
void bookDeleted(BookDeleted bookDeleted) {
log.info("Deleting book [$bookDeleted]")
bookSuccessfulyDeleted.set(true)
}
AtomicBoolean bookSuccessfulyDeleted = new AtomicBoolean(false)
}

View File

@@ -0,0 +1,14 @@
package io.codearte.accurest.samples.book
import com.fasterxml.jackson.annotation.JsonCreator
import groovy.transform.CompileStatic
@CompileStatic
class BookReturned {
final String bookName
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
BookReturned(String bookName) {
this.bookName = bookName
}
}

View File

@@ -0,0 +1,32 @@
package io.codearte.accurest.samples.book
import groovy.transform.CompileStatic
import groovy.util.logging.Slf4j
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.messaging.MessageChannel
import org.springframework.messaging.MessageHeaders
import org.springframework.messaging.support.MessageBuilder
import org.springframework.stereotype.Service
@Service
@CompileStatic
@Slf4j
class BookService {
@Autowired @Qualifier("outputChannel") MessageChannel outputChannel
/**
Scenario for "should generate tests triggered by a method":
client side: must have a possibility to "trigger" sending of a message to the given messageFrom
server side: will run the method and await upon receiving message on the output messageFrom
Method triggers sending a message to a source
*/
void returnBook(BookReturned bookReturned) {
log.info("Returning book [$bookReturned]")
outputChannel.send(MessageBuilder.createMessage(bookReturned, new MessageHeaders([
'BOOK-NAME': bookReturned.bookName as Object
])))
}
}

View File

@@ -0,0 +1,14 @@
package io.codearte.accurest.samples.book
import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.context.annotation.ImportResource
@SpringBootApplication
@ImportResource("classpath*:integration-context.xml")
class IntegrationMessagingApplication {
static void main(String[] args) {
SpringApplication.run(IntegrationMessagingApplication.class, args)
}
}

View File

@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration
http://www.springframework.org/schema/integration/spring-integration.xsd">
<channel id="input"/>
<channel id="delete"/>
<channel id="outputChannel"/>
<service-activator input-channel="inputChannel"
output-channel="outputChannel"
ref="bookListener"
method="returnBook"/>
<json-to-object-transformer input-channel="input" type="io.codearte.accurest.samples.book.BookReturned"
output-channel="inputChannel"/>
<service-activator input-channel="deleteChannel"
ref="bookListener"
method="bookDeleted"/>
<json-to-object-transformer input-channel="delete" type="io.codearte.accurest.samples.book.BookDeleted"
output-channel="deleteChannel"/>
<beans:bean id="bookListener" class="io.codearte.accurest.samples.book.BookListener"/>
<!-- REQUIRED FOR TESTING -->
<bridge input-channel="outputChannel"
output-channel="output"/>
<channel id="output">
<queue/>
</channel>
</beans:beans>

View File

@@ -0,0 +1,25 @@
package io.codearte.accurest.samples.book
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.SpringApplicationContextLoader
import org.springframework.test.context.ContextConfiguration
import spock.lang.Specification
/**
* @author Marcin Grzejszczak
*/
@ContextConfiguration(classes = [IntegrationMessagingApplication], loader = SpringApplicationContextLoader)
abstract class MessagingBaseSpec extends Specification {
// BASE CLASS WOULD HAVE THIS:
@Autowired BookService bookService
@Autowired BookListener bookListener
void bookReturnedTriggered() {
bookService.returnBook(new BookReturned("foo"))
}
void bookWasDeleted() {
assert bookListener.bookSuccessfulyDeleted.get()
}
}

View File

@@ -0,0 +1,29 @@
package io.codearte.accurest.samples.book;
import org.assertj.core.api.Assertions;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationContextLoader;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* @author Marcin Grzejszczak
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {IntegrationMessagingApplication.class}, loader = SpringApplicationContextLoader.class)
public abstract class MessagingBaseTest {
// BASE CLASS WOULD HAVE THIS:
@Autowired BookService bookService;
@Autowired BookListener bookListener;
public void bookReturnedTriggered() {
bookService.returnBook(new BookReturned("foo"));
}
public void bookWasDeleted() {
Assertions.assertThat(bookListener.getBookSuccessfulyDeleted().get()).isTrue();
}
}

View File

@@ -0,0 +1,16 @@
repositories {
mavenLocal()
jcenter()
maven {
url "http://repo.spring.io/snapshot"
}
maven {
url "http://repo.spring.io/milestone"
}
}
dependencies {
compile project(':accurest-messaging-root:accurest-messaging-core')
compile 'org.apache.camel:camel-spring:[2.9.0,)'
compile 'org.slf4j:slf4j-api:[1.6.0,)'
}

View File

@@ -0,0 +1,22 @@
package io.codearte.accurest.messaging.camel;
import io.codearte.accurest.messaging.AccurestMessageBuilder;
import io.codearte.accurest.messaging.AccurestMessaging;
import org.apache.camel.CamelContext;
import org.springframework.context.annotation.Bean;
/**
* @author Marcin Grzejszczak
*/
public class AccurestCamelConfiguration {
@Bean
AccurestMessaging accurestMessaging(CamelContext context, AccurestMessageBuilder builder) {
return new AccurestCamelMessaging(context, builder);
}
@Bean
AccurestMessageBuilder accurestMessageBuilder() {
return new AccurestCamelMessageBuilder();
}
}

View File

@@ -0,0 +1,27 @@
package io.codearte.accurest.messaging.camel;
import io.codearte.accurest.messaging.AccurestMessage;
import io.codearte.accurest.messaging.AccurestMessageBuilder;
import org.apache.camel.Message;
import org.apache.camel.impl.DefaultMessage;
import java.util.Map;
/**
* @author Marcin Grzejszczak
*/
public class AccurestCamelMessageBuilder<T> implements AccurestMessageBuilder<T, Message> {
@Override
public AccurestMessage<T, Message> create(T payload, Map<String, Object> headers) {
DefaultMessage message = new DefaultMessage();
message.setBody(payload);
message.setHeaders(headers);
return new CamelMessage<>(message);
}
@Override
public AccurestMessage<T, Message> create(Message message) {
return new CamelMessage<>(message);
}
}

View File

@@ -0,0 +1,82 @@
package io.codearte.accurest.messaging.camel;
import io.codearte.accurest.messaging.AccurestMessage;
import io.codearte.accurest.messaging.AccurestMessageBuilder;
import io.codearte.accurest.messaging.AccurestMessaging;
import org.apache.camel.CamelContext;
import org.apache.camel.ConsumerTemplate;
import org.apache.camel.Exchange;
import org.apache.camel.Message;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.impl.DefaultExchange;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* @author Marcin Grzejszczak
*/
@Component
public class AccurestCamelMessaging<T> implements AccurestMessaging<T, Message> {
private static final Logger log = LoggerFactory.getLogger(AccurestCamelMessaging.class);
private final CamelContext context;
private final AccurestMessageBuilder builder;
@Autowired
@SuppressWarnings("unchecked")
public AccurestCamelMessaging(CamelContext context, AccurestMessageBuilder accurestMessageBuilder) {
this.context = context;
this.builder = accurestMessageBuilder;
}
@Override
public void send(AccurestMessage<T, Message> message, String destination) {
try {
ProducerTemplate producerTemplate = context.createProducerTemplate();
Exchange exchange = new DefaultExchange(context);
exchange.setIn(message.convert());
producerTemplate.send(destination, exchange);
} catch (Exception e) {
log.error("Exception occurred while trying to send a message [" + message + "] " +
"to a channel with name [" + destination + "]", e);
throw e;
}
}
@Override
@SuppressWarnings("unchecked")
public AccurestMessage<T, Message> receiveMessage(String destination, long timeout, TimeUnit timeUnit) {
try {
ConsumerTemplate consumerTemplate = context.createConsumerTemplate();
Exchange exchange = consumerTemplate.receive(destination, timeUnit.toMillis(timeout));
return builder.create(exchange.getIn());
} catch (Exception e) {
log.error("Exception occurred while trying to read a message from " +
" a channel with name [" + destination + "]", e);
throw new RuntimeException(e);
}
}
@Override
public AccurestMessage<T, Message> receiveMessage(String destination) {
return receiveMessage(destination, 5, TimeUnit.SECONDS);
}
@Override
@SuppressWarnings("unchecked")
public AccurestMessage<T, Message> create(T t, Map<String, Object> headers) {
return builder.create(t, headers);
}
@Override
@SuppressWarnings("unchecked")
public AccurestMessage<T, Message> create(Message message) {
return builder.create(message);
}
}

View File

@@ -0,0 +1,40 @@
package io.codearte.accurest.messaging.camel;
import io.codearte.accurest.messaging.AccurestMessage;
import org.apache.camel.Message;
import java.util.Map;
/**
* @author Marcin Grzejszczak
*/
public class CamelMessage<T> implements AccurestMessage<T, Message> {
private final Message delegate;
public CamelMessage(Message delegate) {
this.delegate = delegate;
}
@Override
@SuppressWarnings("unchecked")
public T getPayload() {
return (T) delegate.getBody();
}
@Override
public Map<String, Object> getHeaders() {
return delegate.getHeaders();
}
@Override
public Object getHeader(String key) {
return getHeaders().get(key);
}
@Override
public Message convert() {
return delegate;
}
}

View File

@@ -0,0 +1,3 @@
# Auto Configuration
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
io.codearte.accurest.messaging.camel.AccurestCamelConfiguration

View File

@@ -0,0 +1,8 @@
repositories {
jcenter()
}
dependencies {
compile 'com.fasterxml.jackson.core:jackson-databind:[2.4.4,)'
compile 'javax.inject:javax.inject:1'
}

View File

@@ -0,0 +1,32 @@
package io.codearte.accurest.messaging;
import java.util.Map;
/**
* Describes a message. Contains payload and headers. A message can be converted
* to another type (e.g. Spring Messaging Message)
*
* @author Marcin Grzejszczak
*/
public interface AccurestMessage<PAYLOAD, TYPE_TO_CONVERT_INTO> {
/**
* Returns a payload of type {@code PAYLOAD}
*/
PAYLOAD getPayload();
/**
* Returns a map of headers
*/
Map<String, Object> getHeaders();
/**
* Returns a header for a given key
*/
Object getHeader(String key);
/**
* Converts the message to {@code TYPE_TO_CONVERT_INTO} type
*/
TYPE_TO_CONVERT_INTO convert();
}

View File

@@ -0,0 +1,22 @@
package io.codearte.accurest.messaging;
import java.util.Map;
/**
* Contract for creation of (@link AccurestMessage}. You can create a message from
* payload and headers or from some type (e.g. Spring Messaging Message).
*
* @author Marcin Grzejszczak
*/
public interface AccurestMessageBuilder<PAYLOAD, TYPE_TO_CONVERT_INTO> {
/**
* Creates a {@link AccurestMessage} from payload and headers
*/
AccurestMessage<PAYLOAD, TYPE_TO_CONVERT_INTO> create(PAYLOAD payload, Map<String, Object> headers);
/**
* Creates a {@link AccurestMessage} from the {@code TYPE_TO_CONVERT_INTO} type
*/
AccurestMessage<PAYLOAD, TYPE_TO_CONVERT_INTO> create(TYPE_TO_CONVERT_INTO typeToConvertInto);
}

View File

@@ -0,0 +1,28 @@
package io.codearte.accurest.messaging;
import java.util.concurrent.TimeUnit;
/**
* Core interface that allows you to build, send and receive messages.
*
* Destination is relevant to the underlaying implementation. Might be a channel, queue, topic etc.
*
* @author Marcin Grzejszczak
*/
public interface AccurestMessaging<PAYLOAD, TYPE_TO_CONVERT_INTO> extends AccurestMessageBuilder<PAYLOAD, TYPE_TO_CONVERT_INTO> {
/**
* Sends the {@link AccurestMessage} to the given destination.
*/
void send(AccurestMessage<PAYLOAD, TYPE_TO_CONVERT_INTO> message, String destination);
/**
* Receives the {@link AccurestMessage} from the given destination. You can provide the timeout
* for receiving that message.
*/
AccurestMessage<PAYLOAD, TYPE_TO_CONVERT_INTO> receiveMessage(String destination, long timeout, TimeUnit timeUnit);
/**
* Receives the {@link AccurestMessage} from the given destination. A default timeout will be applied.
*/
AccurestMessage<PAYLOAD, TYPE_TO_CONVERT_INTO> receiveMessage(String destination);
}

View File

@@ -0,0 +1,98 @@
package io.codearte.accurest.messaging;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* Helper class that allows to build headers in a nice way
*
* @author Marcin Grzejszczak
*/
public class AccurestMessagingUtil {
public static AccurestHeaders headers() {
return new AccurestHeaders();
}
public static class AccurestHeaders implements Map<String, Object> {
private final Map<String, Object> delegate = new HashMap<>();
public AccurestHeaders header(String key, Object value) {
put(key, value);
return this;
}
@Override
public int size() {
return delegate.size();
}
@Override
public boolean isEmpty() {
return delegate.isEmpty();
}
@Override
public boolean containsKey(Object key) {
return delegate.containsKey(key);
}
@Override
public boolean containsValue(Object value) {
return delegate.containsValue(value);
}
@Override
public Object get(Object key) {
return delegate.get(key);
}
@Override
public Object put(String key, Object value) {
return delegate.put(key, value);
}
@Override
public Object remove(Object key) {
return delegate.remove(key);
}
@Override
public void putAll(Map<? extends String, ?> m) {
delegate.putAll(m);
}
@Override
public void clear() {
delegate.clear();
}
@Override
public Set<String> keySet() {
return delegate.keySet();
}
@Override
public Collection<Object> values() {
return delegate.values();
}
@Override
public Set<Entry<String, Object>> entrySet() {
return delegate.entrySet();
}
@Override
public boolean equals(Object o) {
return delegate.equals(o);
}
@Override
public int hashCode() {
return delegate.hashCode();
}
}
}

View File

@@ -0,0 +1,30 @@
package io.codearte.accurest.messaging.noop;
import io.codearte.accurest.messaging.AccurestMessage;
import java.util.Map;
/**
* @author Marcin Grzejszczak
*/
public class NoOpAccurestMessage implements AccurestMessage {
@Override
public Object getPayload() {
return null;
}
@Override
public Map<String, Object> getHeaders() {
return null;
}
@Override
public Object getHeader(String key) {
return null;
}
@Override
public Object convert() {
return null;
}
}

View File

@@ -0,0 +1,21 @@
package io.codearte.accurest.messaging.noop;
import io.codearte.accurest.messaging.AccurestMessage;
import io.codearte.accurest.messaging.AccurestMessageBuilder;
import java.util.Map;
/**
* @author Marcin Grzejszczak
*/
public class NoOpAccurestMessageBuilder implements AccurestMessageBuilder {
@Override
public AccurestMessage create(Object o, Map headers) {
return null;
}
@Override
public AccurestMessage create(Object o) {
return null;
}
}

View File

@@ -0,0 +1,37 @@
package io.codearte.accurest.messaging.noop;
import io.codearte.accurest.messaging.AccurestMessage;
import io.codearte.accurest.messaging.AccurestMessaging;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* @author Marcin Grzejszczak
*/
public class NoOpAccurestMessaging implements AccurestMessaging {
@Override
public void send(AccurestMessage message, String destination) {
}
@Override
public AccurestMessage receiveMessage(String destination, long timeout, TimeUnit timeUnit) {
return null;
}
@Override
public AccurestMessage receiveMessage(String destination) {
return null;
}
@Override
public AccurestMessage create(Object o, Map headers) {
return null;
}
@Override
public AccurestMessage create(Object o) {
return null;
}
}

View File

@@ -0,0 +1,16 @@
repositories {
mavenLocal()
jcenter()
maven {
url "http://repo.spring.io/snapshot"
}
maven {
url "http://repo.spring.io/milestone"
}
}
dependencies {
compile project(':accurest-messaging-root:accurest-messaging-core')
compile 'org.springframework:spring-messaging:[4.0.0.RELEASE,)'
compile 'org.slf4j:slf4j-api:[1.6.0,)'
}

View File

@@ -0,0 +1,22 @@
package io.codearte.accurest.messaging.integration;
import io.codearte.accurest.messaging.AccurestMessageBuilder;
import io.codearte.accurest.messaging.AccurestMessaging;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
/**
* @author Marcin Grzejszczak
*/
public class AccurestIntegrationConfiguration {
@Bean
AccurestMessaging accurestMessaging(ApplicationContext applicationContext, AccurestMessageBuilder accurestMessageBuilder) {
return new AccurestIntegrationMessaging(applicationContext, accurestMessageBuilder);
}
@Bean
AccurestMessageBuilder accurestMessageBuilder() {
return new AccurestIntegrationMessageBuilder();
}
}

View File

@@ -0,0 +1,25 @@
package io.codearte.accurest.messaging.integration;
import io.codearte.accurest.messaging.AccurestMessage;
import io.codearte.accurest.messaging.AccurestMessageBuilder;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHeaders;
import org.springframework.messaging.support.MessageBuilder;
import java.util.Map;
/**
* @author Marcin Grzejszczak
*/
public class AccurestIntegrationMessageBuilder<T> implements AccurestMessageBuilder<T, Message<T>> {
@Override
public AccurestMessage<T, Message<T>> create(T payload, Map<String, Object> headers) {
return new IntegrationMessage<>(MessageBuilder.createMessage(payload, new MessageHeaders(headers)));
}
@Override
public AccurestMessage<T, Message<T>> create(Message<T> message) {
return new IntegrationMessage<>(message);
}
}

View File

@@ -0,0 +1,77 @@
package io.codearte.accurest.messaging.integration;
import io.codearte.accurest.messaging.AccurestMessage;
import io.codearte.accurest.messaging.AccurestMessageBuilder;
import io.codearte.accurest.messaging.AccurestMessaging;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.PollableChannel;
import org.springframework.stereotype.Component;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* @author Marcin Grzejszczak
*/
@Component
public class AccurestIntegrationMessaging<T> implements AccurestMessaging<T, Message<T>> {
private static final Logger log = LoggerFactory.getLogger(AccurestIntegrationMessaging.class);
private final ApplicationContext context;
private final AccurestMessageBuilder builder;
@Autowired
@SuppressWarnings("unchecked")
public AccurestIntegrationMessaging(ApplicationContext context, AccurestMessageBuilder accurestMessageBuilder) {
this.context = context;
this.builder = accurestMessageBuilder;
}
@Override
public void send(AccurestMessage<T, Message<T>> message, String destination) {
try {
MessageChannel messageChannel = context.getBean(destination, MessageChannel.class);
messageChannel.send(message.convert());
} catch (Exception e) {
log.error("Exception occurred while trying to send a message [" + message + "] " +
"to a channel with name [" + destination + "]", e);
throw e;
}
}
@Override
@SuppressWarnings("unchecked")
public AccurestMessage<T, Message<T>> receiveMessage(String destination, long timeout, TimeUnit timeUnit) {
try {
PollableChannel messageChannel = context.getBean(destination, PollableChannel.class);
return builder.create(messageChannel.receive(timeUnit.toMillis(timeout)));
} catch (Exception e) {
log.error("Exception occurred while trying to read a message from " +
" a channel with name [" + destination + "]", e);
throw new RuntimeException(e);
}
}
@Override
public AccurestMessage<T, Message<T>> receiveMessage(String destination) {
return receiveMessage(destination, 5, TimeUnit.SECONDS);
}
@Override
@SuppressWarnings("unchecked")
public AccurestMessage<T, Message<T>> create(T t, Map<String, Object> headers) {
return builder.create(t, headers);
}
@Override
@SuppressWarnings("unchecked")
public AccurestMessage<T, Message<T>> create(Message<T> message) {
return builder.create(message);
}
}

View File

@@ -0,0 +1,38 @@
package io.codearte.accurest.messaging.integration;
import io.codearte.accurest.messaging.AccurestMessage;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHeaders;
/**
* @author Marcin Grzejszczak
*/
public class IntegrationMessage<T> implements AccurestMessage<T, Message<T>> {
private final Message<T> delegate;
public IntegrationMessage(Message<T> delegate) {
this.delegate = delegate;
}
@Override
public T getPayload() {
return delegate.getPayload();
}
@Override
public MessageHeaders getHeaders() {
return delegate.getHeaders();
}
@Override
public Object getHeader(String key) {
return getHeaders().get(key);
}
@Override
public Message<T> convert() {
return delegate;
}
}

View File

@@ -0,0 +1,3 @@
# Auto Configuration
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
io.codearte.accurest.messaging.integration.AccurestIntegrationConfiguration

View File

@@ -0,0 +1,16 @@
repositories {
mavenLocal()
jcenter()
maven {
url "http://repo.spring.io/snapshot"
}
maven {
url "http://repo.spring.io/milestone"
}
}
dependencies {
compile project(':accurest-messaging-root:accurest-messaging-core')
compile 'org.springframework:spring-messaging:[4.0.0.RELEASE,)'
compile 'org.springframework.cloud:spring-cloud-stream-test-support:[1.0.0.RC2,)'
}

View File

@@ -0,0 +1,24 @@
package io.codearte.accurest.messaging.stream;
import io.codearte.accurest.messaging.AccurestMessageBuilder;
import io.codearte.accurest.messaging.AccurestMessaging;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author Marcin Grzejszczak
*/
@Configuration
public class AccurestStreamAutoConfiguration {
@Bean
AccurestMessaging accurestMessaging(ApplicationContext applicationContext, AccurestMessageBuilder accurestMessageBuilder) {
return new AccurestStreamMessaging(applicationContext, accurestMessageBuilder);
}
@Bean
AccurestMessageBuilder accurestMessageBuilder() {
return new AccurestStreamMessageBuilder();
}
}

View File

@@ -0,0 +1,25 @@
package io.codearte.accurest.messaging.stream;
import io.codearte.accurest.messaging.AccurestMessage;
import io.codearte.accurest.messaging.AccurestMessageBuilder;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHeaders;
import org.springframework.messaging.support.MessageBuilder;
import java.util.Map;
/**
* @author Marcin Grzejszczak
*/
public class AccurestStreamMessageBuilder<T> implements AccurestMessageBuilder<T, Message<T>> {
@Override
public AccurestMessage<T, Message<T>> create(T payload, Map<String, Object> headers) {
return new StreamMessage<>(MessageBuilder.createMessage(payload, new MessageHeaders(headers)));
}
@Override
public AccurestMessage<T, Message<T>> create(Message<T> message) {
return new StreamMessage<>(message);
}
}

View File

@@ -0,0 +1,77 @@
package io.codearte.accurest.messaging.stream;
import io.codearte.accurest.messaging.AccurestMessage;
import io.codearte.accurest.messaging.AccurestMessageBuilder;
import io.codearte.accurest.messaging.AccurestMessaging;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.stream.test.binder.MessageCollector;
import org.springframework.context.ApplicationContext;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* @author Marcin Grzejszczak
*/
public class AccurestStreamMessaging<T> implements AccurestMessaging<T, Message<T>> {
private static final Logger log = LoggerFactory.getLogger(AccurestStreamMessaging.class);
private final ApplicationContext context;
private final MessageCollector messageCollector;
private final AccurestMessageBuilder builder;
@Autowired
@SuppressWarnings("unchecked")
public AccurestStreamMessaging(ApplicationContext context, AccurestMessageBuilder builder) {
this.context = context;
this.messageCollector = context.getBean(MessageCollector.class);
this.builder = builder;
}
@Override
public void send(AccurestMessage<T, Message<T>> message, String destination) {
try {
MessageChannel messageChannel = context.getBean(destination, MessageChannel.class);
messageChannel.send(message.convert());
} catch (Exception e) {
log.error("Exception occurred while trying to send a message [" + message + "] " +
"to a channel with name [" + destination + "]", e);
throw e;
}
}
@Override
@SuppressWarnings("unchecked")
public AccurestMessage<T, Message<T>> receiveMessage(String destination, long timeout, TimeUnit timeUnit) {
try {
MessageChannel messageChannel = context.getBean(destination, MessageChannel.class);
return builder.create(messageCollector.forChannel(messageChannel).poll(timeout, timeUnit));
} catch (Exception e) {
log.error("Exception occurred while trying to read a message from " +
" a channel with name [" + destination + "]", e);
throw new RuntimeException(e);
}
}
@Override
public AccurestMessage<T, Message<T>> receiveMessage(String destination) {
return receiveMessage(destination, 5, TimeUnit.SECONDS);
}
@Override
@SuppressWarnings("unchecked")
public AccurestMessage<T, Message<T>> create(T t, Map<String, Object> headers) {
return builder.create(t, headers);
}
@Override
@SuppressWarnings("unchecked")
public AccurestMessage<T, Message<T>> create(Message<T> message) {
return builder.create(message);
}
}

View File

@@ -0,0 +1,38 @@
package io.codearte.accurest.messaging.stream;
import io.codearte.accurest.messaging.AccurestMessage;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHeaders;
/**
* @author Marcin Grzejszczak
*/
public class StreamMessage<T> implements AccurestMessage<T, Message<T>> {
private final Message<T> delegate;
public StreamMessage(Message<T> delegate) {
this.delegate = delegate;
}
@Override
public T getPayload() {
return delegate.getPayload();
}
@Override
public MessageHeaders getHeaders() {
return delegate.getHeaders();
}
@Override
public Object getHeader(String key) {
return getHeaders().get(key);
}
@Override
public Message<T> convert() {
return delegate;
}
}

View File

@@ -0,0 +1,3 @@
# Auto Configuration
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
io.codearte.accurest.messaging.stream.AccurestStreamAutoConfiguration

View File

@@ -9,7 +9,6 @@ buildscript {
classpath "com.bmuschko:gradle-nexus-plugin:2.3"
classpath "io.codearte.gradle.nexus:gradle-nexus-staging-plugin:0.5.3"
if (project.hasProperty('fatJar')) classpath 'com.github.jengelman.gradle.plugins:shadow:1.2.3'
classpath "io.spring.gradle:dependency-management-plugin:0.5.6.RELEASE"
}
}
@@ -98,7 +97,7 @@ project(':accurest-core') {
compile "com.github.tomakehurst:wiremock:$wiremockVersion"
compile "com.toomuchcoding.jsonassert:jsonassert:$jsonassertVersion"
compile 'org.assertj:assertj-core:2.3.0'
compile 'org.codehaus.groovy:groovy-all:2.4.4'
compile localGroovy()
testCompile 'cglib:cglib-nodep:2.2'
testCompile 'org.objenesis:objenesis:2.1'
testCompile project(':accurest-testing-utils')
@@ -129,8 +128,8 @@ project(':accurest-gradle-plugin') {
dependencies {
compile project(':accurest-core')
compile project(':accurest-converters')
compile gradleApi()
testCompile('com.netflix.nebula:nebula-test:4.0.0') {
exclude(group: 'org.spockframework')
}
@@ -148,6 +147,10 @@ project(':accurest-gradle-plugin') {
}
}
// Hack for reusing this in the plugin test
test.dependsOn(':accurest-core:install')
test.dependsOn(':accurest-messaging-root:accurest-messaging-core:install')
test.dependsOn(':accurest-messaging-root:accurest-messaging-integration:install')
uploadArchives.dependsOn { funcTest }
}

View File

@@ -2,4 +2,6 @@ nexusUsername =
nexusPassword =
wiremockVersion = 2.0.5-beta
jsonassertVersion = 0.2.2
jsonassertVersion = 0.2.2
BOM_VERSION=Brixton-1.0.0.RC1

View File

@@ -0,0 +1,26 @@
repositories {
mavenLocal()
jcenter()
maven {
url "http://repo.spring.io/snapshot"
}
maven {
url "http://repo.spring.io/milestone"
}
}
dependencies {
compile project(':accurest-core')
compile 'org.springframework.boot:spring-boot-starter-actuator:1.3.3.RELEASE'
compile 'org.apache.camel:camel-spring-boot-starter:2.17.0'
compile 'org.apache.camel:camel-jms:2.17.0'
compile 'org.apache.activemq:activemq-camel:5.12.1'
compile 'org.apache.activemq:activemq-pool:5.12.1'
compile 'org.apache.camel:camel-jackson:2.17.0'
testCompile project(':accurest-messaging-root:accurest-messaging-camel')
testCompile 'org.springframework.boot:spring-boot-starter-test:1.3.3.RELEASE'
testCompile('org.spockframework:spock-spring:1.0-groovy-2.4') {
exclude(group: 'org.codehaus.groovy')
}
}

View File

@@ -0,0 +1,14 @@
package io.codearte.accurest.samples.camel
import com.fasterxml.jackson.annotation.JsonCreator
import groovy.transform.CompileStatic
@CompileStatic
class BookDeleted implements Serializable {
final String bookName
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
BookDeleted(String bookName) {
this.bookName = bookName
}
}

View File

@@ -0,0 +1,28 @@
package io.codearte.accurest.samples.camel
import groovy.transform.CompileStatic
import groovy.util.logging.Slf4j
import org.apache.camel.Exchange
import org.springframework.stereotype.Component
import java.util.concurrent.atomic.AtomicBoolean
@CompileStatic
@Slf4j
@Component
class BookDeleter {
/**
Scenario for "should generate tests triggered by a message":
client side: if sends a message to input.messageFrom then message will be sent to output.messageFrom
server side: will send a message to input, verify the message contents and await upon receiving message on the output messageFrom
*/
void bookDeleted(Exchange exchange) {
BookDeleted bookDeleted = exchange.in.getBody(BookDeleted)
log.info("Deleting book [$bookDeleted]")
bookSuccessfulyDeleted.set(true)
log.info("Book successfuly deleted [$bookSuccessfulyDeleted]")
}
AtomicBoolean bookSuccessfulyDeleted = new AtomicBoolean(false)
}

View File

@@ -0,0 +1,14 @@
package io.codearte.accurest.samples.camel
import com.fasterxml.jackson.annotation.JsonCreator
import groovy.transform.CompileStatic
@CompileStatic
class BookReturned implements Serializable {
final String bookName
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
BookReturned(String bookName) {
this.bookName = bookName
}
}

View File

@@ -0,0 +1,37 @@
package io.codearte.accurest.samples.camel
import org.apache.activemq.camel.component.ActiveMQComponent
import org.apache.camel.RoutesBuilder
import org.apache.camel.model.dataformat.JsonLibrary
import org.apache.camel.spring.SpringRouteBuilder
import org.springframework.beans.factory.annotation.Value
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
/**
* @author Marcin Grzejszczak
*/
@Configuration
class BookRouteConfiguration {
@Bean
ActiveMQComponent activeMQComponent(@Value('${activemq.url:vm://localhost?broker.persistent=false}') String url) {
return new ActiveMQComponent(brokerURL: url)
}
@Bean
RoutesBuilder myRouter(BookService bookService, BookDeleter bookDeleter) {
return new SpringRouteBuilder() {
@Override
public void configure() throws Exception {
// scenario 1 - from bean to output
from("direct:start").unmarshal().json(JsonLibrary.Jackson, BookReturned).bean(bookService).to("jms:output")
// scenario 2 - from input to output
from("jms:input").unmarshal().json(JsonLibrary.Jackson, BookReturned).bean(bookService).to("jms:output")
// scenario 3 - from input to no output
from("jms:delete").unmarshal().json(JsonLibrary.Jackson, BookDeleted).bean(bookDeleter)
}
};
}
}

View File

@@ -0,0 +1,28 @@
package io.codearte.accurest.samples.camel
import groovy.transform.CompileStatic
import groovy.util.logging.Slf4j
import org.apache.camel.Exchange
import org.springframework.stereotype.Service
@Service
@CompileStatic
@Slf4j
class BookService {
/**
Scenario for "should generate tests triggered by a method":
client side: must have a possibility to "trigger" sending of a message to the given messageFrom
server side: will run the method and await upon receiving message on the output messageFrom
Method triggers sending a message to a source
*/
void returnBook(Exchange exchange) {
BookReturned bookReturned = exchange.in.getBody(BookReturned)
log.info("Returning book [$bookReturned]")
exchange.out.with {
body = bookReturned
setHeader('BOOK-NAME', bookReturned.bookName)
}
}
}

View File

@@ -0,0 +1,12 @@
package io.codearte.accurest.samples.camel
import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
@SpringBootApplication
class CamelMessagingApplication {
static void main(String[] args) {
SpringApplication.run(CamelMessagingApplication.class, args)
}
}

View File

@@ -0,0 +1,144 @@
package io.codearte.accurest.samples.camel
import com.fasterxml.jackson.databind.ObjectMapper
import com.jayway.jsonpath.DocumentContext
import com.jayway.jsonpath.JsonPath
import com.toomuchcoding.jsonassert.JsonAssertion
import io.codearte.accurest.dsl.GroovyDsl
import io.codearte.accurest.messaging.AccurestMessage
import io.codearte.accurest.messaging.AccurestMessaging
import org.apache.camel.model.ModelCamelContext
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.SpringApplicationContextLoader
import org.springframework.test.context.ContextConfiguration
import spock.lang.Specification
import spock.util.concurrent.PollingConditions
import javax.inject.Inject
/**
* SPIKE ON TESTS FROM NOTES IN MessagingSpec
*/
// Context configuration would end up in base class
@ContextConfiguration(classes = [CamelMessagingApplication], loader = SpringApplicationContextLoader)
public class CamelMessagingApplicationSpec extends Specification {
// ALL CASES
@Inject AccurestMessaging accurestMessaging
ObjectMapper accurestObjectMapper = new ObjectMapper()
def "should work for triggered based messaging"() {
given:
def dsl = GroovyDsl.make {
label 'some_label'
input {
triggeredBy('bookReturnedTriggered()')
}
outputMessage {
sentTo('activemq:output')
body('''{ "bookName" : "foo" }''')
headers {
header('BOOK-NAME', 'foo')
}
}
}
// generated test should look like this:
when:
bookReturnedTriggered()
then:
def response = accurestMessaging.receiveMessage('activemq:output')
response.headers.get('BOOK-NAME') == 'foo'
and:
DocumentContext parsedJson = JsonPath.parse(accurestObjectMapper.writeValueAsString(response.payload))
JsonAssertion.assertThat(parsedJson).field('bookName').isEqualTo('foo')
}
def "should generate tests triggered by a message"() {
given:
def dsl = GroovyDsl.make {
label 'some_label'
input {
messageFrom('jms:input')
messageBody([
bookName: 'foo'
])
messageHeaders {
header('sample', 'header')
header('Content-Type', 'application/json')
}
}
outputMessage {
sentTo('jms:output')
body([
bookName: 'foo'
])
headers {
header('BOOK-NAME', 'foo')
}
}
}
// generated test should look like this:
//given:
AccurestMessage inputMessage = accurestMessaging.create(
accurestObjectMapper.writeValueAsString([bookName: 'foo']),
[sample: 'header']
)
when:
accurestMessaging.send(inputMessage, 'jms:input')
then:
def response = accurestMessaging.receiveMessage('jms:output')
response.headers.get('BOOK-NAME') == 'foo'
and:
DocumentContext parsedJson = JsonPath.parse(accurestObjectMapper.writeValueAsString(response.payload))
JsonAssertion.assertThat(parsedJson).field('bookName').isEqualTo('foo')
}
def "should generate tests without destination, triggered by a message"() {
given:
def dsl = GroovyDsl.make {
label 'some_label'
input {
messageFrom('jms:delete')
messageBody([
bookName: 'foo'
])
messageHeaders {
header('sample', 'header')
}
assertThat('bookWasDeleted()')
}
}
// generated test should look like this:
//given:
AccurestMessage inputMessage = accurestMessaging.create(
accurestObjectMapper.writeValueAsString([bookName: 'foo']),
[sample: 'header']
)
when:
accurestMessaging.send(inputMessage, 'jms:delete')
then:
noExceptionThrown()
bookWasDeleted()
}
// BASE CLASS WOULD HAVE THIS:
@Autowired ModelCamelContext camelContext
@Autowired BookDeleter bookDeleter
void bookReturnedTriggered() {
camelContext.createProducerTemplate().sendBody('direct:start', '''{"bookName" : "foo" }''')
}
PollingConditions pollingConditions = new PollingConditions()
void bookWasDeleted() {
pollingConditions.eventually {
assert bookDeleter.bookSuccessfulyDeleted.get()
}
}
}

View File

@@ -0,0 +1,23 @@
repositories {
mavenLocal()
jcenter()
maven {
url "http://repo.spring.io/snapshot"
}
maven {
url "http://repo.spring.io/milestone"
}
}
dependencies {
compile project(':accurest-core')
compile 'org.springframework.boot:spring-boot-starter-actuator:1.3.3.RELEASE'
compile 'org.springframework.boot:spring-boot-starter-integration:1.3.3.RELEASE'
compile 'org.springframework:spring-messaging:[4.0.0.RELEASE,)'
testCompile project(':accurest-messaging-root:accurest-messaging-integration')
testCompile 'org.springframework.boot:spring-boot-starter-test:1.3.3.RELEASE'
testCompile('org.spockframework:spock-spring:1.0-groovy-2.4') {
exclude(group: 'org.codehaus.groovy')
}
}

View File

@@ -0,0 +1,14 @@
package io.codearte.accurest.samples.messaging
import com.fasterxml.jackson.annotation.JsonCreator
import groovy.transform.CompileStatic
@CompileStatic
class BookDeleted {
final String bookName
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
BookDeleted(String bookName) {
this.bookName = bookName
}
}

View File

@@ -0,0 +1,38 @@
package io.codearte.accurest.samples.messaging
import groovy.transform.CompileStatic
import groovy.util.logging.Slf4j
import org.springframework.messaging.Message
import org.springframework.messaging.MessageHeaders
import org.springframework.messaging.support.MessageBuilder
import java.util.concurrent.atomic.AtomicBoolean
@CompileStatic
@Slf4j
class BookListener {
/**
Scenario for "should generate tests triggered by a message":
client side: if sends a message to input.messageFrom then message will be sent to output.messageFrom
server side: will send a message to input, verify the message contents and await upon receiving message on the output messageFrom
*/
Message returnBook(BookReturned bookReturned) {
log.info("Returning book [$bookReturned]")
return MessageBuilder.createMessage(bookReturned, new MessageHeaders([
'BOOK-NAME': bookReturned.bookName as Object
]))
}
/**
Scenario for "should generate tests triggered by a message":
client side: if sends a message to input.messageFrom then message will be sent to output.messageFrom
server side: will send a message to input, verify the message contents and await upon receiving message on the output messageFrom
*/
void bookDeleted(BookDeleted bookDeleted) {
log.info("Deleting book [$bookDeleted]")
bookSuccessfulyDeleted.set(true)
}
AtomicBoolean bookSuccessfulyDeleted = new AtomicBoolean(false)
}

View File

@@ -0,0 +1,14 @@
package io.codearte.accurest.samples.messaging
import com.fasterxml.jackson.annotation.JsonCreator
import groovy.transform.CompileStatic
@CompileStatic
class BookReturned {
final String bookName
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
BookReturned(String bookName) {
this.bookName = bookName
}
}

View File

@@ -0,0 +1,32 @@
package io.codearte.accurest.samples.messaging
import groovy.transform.CompileStatic
import groovy.util.logging.Slf4j
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.messaging.MessageChannel
import org.springframework.messaging.MessageHeaders
import org.springframework.messaging.support.MessageBuilder
import org.springframework.stereotype.Service
@Service
@CompileStatic
@Slf4j
class BookService {
@Autowired @Qualifier("outputChannel") MessageChannel outputChannel
/**
Scenario for "should generate tests triggered by a method":
client side: must have a possibility to "trigger" sending of a message to the given messageFrom
server side: will run the method and await upon receiving message on the output messageFrom
Method triggers sending a message to a source
*/
void returnBook(BookReturned bookReturned) {
log.info("Returning book [$bookReturned]")
outputChannel.send(MessageBuilder.createMessage(bookReturned, new MessageHeaders([
'BOOK-NAME': bookReturned.bookName as Object
])))
}
}

View File

@@ -0,0 +1,14 @@
package io.codearte.accurest.samples.messaging
import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.context.annotation.ImportResource
@SpringBootApplication
@ImportResource("classpath*:integration-context.xml")
class IntegrationMessagingApplication {
static void main(String[] args) {
SpringApplication.run(IntegrationMessagingApplication.class, args)
}
}

View File

@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration
http://www.springframework.org/schema/integration/spring-integration.xsd">
<channel id="input"/>
<channel id="delete"/>
<channel id="outputChannel"/>
<service-activator input-channel="inputChannel"
output-channel="outputChannel"
ref="bookListener"
method="returnBook"/>
<json-to-object-transformer input-channel="input" type="io.codearte.accurest.samples.messaging.BookReturned"
output-channel="inputChannel"/>
<service-activator input-channel="deleteChannel"
ref="bookListener"
method="bookDeleted"/>
<json-to-object-transformer input-channel="delete" type="io.codearte.accurest.samples.messaging.BookDeleted"
output-channel="deleteChannel"/>
<beans:bean id="bookListener" class="io.codearte.accurest.samples.messaging.BookListener"/>
<!-- REQUIRED FOR TESTING -->
<bridge input-channel="outputChannel"
output-channel="output"/>
<channel id="output">
<queue/>
</channel>
</beans:beans>

View File

@@ -0,0 +1,138 @@
package io.codearte.accurest.samples.messaging
import com.fasterxml.jackson.databind.ObjectMapper
import com.jayway.jsonpath.DocumentContext
import com.jayway.jsonpath.JsonPath
import com.toomuchcoding.jsonassert.JsonAssertion
import io.codearte.accurest.dsl.GroovyDsl
import io.codearte.accurest.messaging.AccurestMessage
import io.codearte.accurest.messaging.AccurestMessaging
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.SpringApplicationContextLoader
import org.springframework.test.context.ContextConfiguration
import spock.lang.Specification
import javax.inject.Inject
/**
* SPIKE ON TESTS FROM NOTES IN MessagingSpec
*/
// Context configuration would end up in base class
@ContextConfiguration(classes = [IntegrationMessagingApplication], loader = SpringApplicationContextLoader)
public class IntegrationMessagingApplicationSpec extends Specification {
// ALL CASES
@Inject AccurestMessaging accurestMessaging
ObjectMapper accurestObjectMapper = new ObjectMapper()
def "should work for triggered based messaging"() {
given:
def dsl = GroovyDsl.make {
label 'some_label'
input {
triggeredBy('bookReturnedTriggered()')
}
outputMessage {
sentTo('output')
body('''{ "bookName" : "foo" }''')
headers {
header('BOOK-NAME', 'foo')
}
}
}
// generated test should look like this:
when:
bookReturnedTriggered()
then:
def response = accurestMessaging.receiveMessage('output')
response.headers.get('BOOK-NAME') == 'foo'
and:
DocumentContext parsedJson = JsonPath.parse(accurestObjectMapper.writeValueAsString(response.payload))
JsonAssertion.assertThat(parsedJson).field('bookName').isEqualTo('foo')
}
def "should generate tests triggered by a message"() {
given:
def dsl = GroovyDsl.make {
label 'some_label'
input {
messageFrom('input')
messageBody([
bookName: 'foo'
])
messageHeaders {
header('sample', 'header')
}
}
outputMessage {
sentTo('output')
body([
bookName: 'foo'
])
headers {
header('BOOK-NAME', 'foo')
}
}
}
// generated test should look like this:
//given:
AccurestMessage inputMessage = accurestMessaging.create(
accurestObjectMapper.writeValueAsString([bookName: 'foo']),
[sample: 'header']
)
when:
accurestMessaging.send(inputMessage, 'input')
then:
def response = accurestMessaging.receiveMessage('output')
response.headers.get('BOOK-NAME') == 'foo'
and:
DocumentContext parsedJson = JsonPath.parse(accurestObjectMapper.writeValueAsString(response.payload))
JsonAssertion.assertThat(parsedJson).field('bookName').isEqualTo('foo')
}
def "should generate tests without destination, triggered by a message"() {
given:
def dsl = GroovyDsl.make {
label 'some_label'
input {
messageFrom('delete')
messageBody([
bookName: 'foo'
])
messageHeaders {
header('sample', 'header')
}
assertThat('bookWasDeleted()')
}
}
// generated test should look like this:
//given:
AccurestMessage inputMessage = accurestMessaging.create(
accurestObjectMapper.writeValueAsString([bookName: 'foo']),
[sample: 'header']
)
when:
accurestMessaging.send(inputMessage, 'delete')
then:
noExceptionThrown()
bookWasDeleted()
}
// BASE CLASS WOULD HAVE THIS:
@Autowired BookService bookService
@Autowired BookListener bookListener
void bookReturnedTriggered() {
bookService.returnBook(new BookReturned("foo"))
}
void bookWasDeleted() {
assert bookListener.bookSuccessfulyDeleted.get()
}
}

View File

@@ -0,0 +1,25 @@
repositories {
mavenLocal()
jcenter()
maven {
url "http://repo.spring.io/snapshot"
}
maven {
url "http://repo.spring.io/milestone"
}
}
dependencies {
compile project(':accurest-core')
compile 'org.springframework.boot:spring-boot-starter-actuator:1.3.3.RELEASE'
compile 'org.springframework:spring-jms:4.2.3.RELEASE'
compile 'org.apache.activemq:activemq-broker:5.12.1'
compile 'org.apache.activemq:activemq-pool:5.12.1'
testCompile project(':accurest-messaging-root:accurest-messaging-core')
testCompile 'org.springframework.boot:spring-boot-starter-test:1.3.3.RELEASE'
testCompile('org.spockframework:spock-spring:1.0-groovy-2.4') {
exclude(group: 'org.codehaus.groovy')
}
}

View File

@@ -0,0 +1,14 @@
package io.codearte.accurest.samples.spring
import com.fasterxml.jackson.annotation.JsonCreator
import groovy.transform.CompileStatic
@CompileStatic
class BookDeleted implements Serializable {
final String bookName
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
BookDeleted(String bookName) {
this.bookName = bookName
}
}

View File

@@ -0,0 +1,58 @@
package io.codearte.accurest.samples.spring
import com.fasterxml.jackson.databind.ObjectMapper
import groovy.transform.CompileStatic
import groovy.util.logging.Slf4j
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.jms.annotation.JmsListener
import org.springframework.jms.core.JmsTemplate
import org.springframework.jms.core.MessageCreator
import org.springframework.stereotype.Service
import javax.jms.JMSException
import javax.jms.Message
import javax.jms.Session
import java.util.concurrent.atomic.AtomicBoolean
@CompileStatic
@Slf4j
@Service
class BookListener {
@Autowired JmsTemplate jmsTemplate
ObjectMapper objectMapper = new ObjectMapper()
/**
Scenario for "should generate tests triggered by a message":
client side: if sends a message to input.messageFrom then message will be sent to output.messageFrom
server side: will send a message to input, verify the message contents and await upon receiving message on the output messageFrom
*/
@JmsListener(destination = "input")
void returnBook(String messageAsString) {
BookReturned bookReturned = objectMapper.readerFor(BookReturned).readValue(messageAsString) as BookReturned
log.info("Returning book [$bookReturned]")
MessageCreator messageCreator = new MessageCreator() {
@Override
public Message createMessage(Session session) throws JMSException {
Message message = session.createObjectMessage(bookReturned);
message.setStringProperty('BOOK-NAME', bookReturned.bookName)
return message
}
};
jmsTemplate.send('output', messageCreator)
}
/**
Scenario for "should generate tests triggered by a message":
client side: if sends a message to input.messageFrom then message will be sent to output.messageFrom
server side: will send a message to input, verify the message contents and await upon receiving message on the output messageFrom
*/
@JmsListener(destination = "delete")
void bookDeleted(String bookDeletedAsString) {
BookDeleted bookDeleted = objectMapper.readerFor(BookDeleted).readValue(bookDeletedAsString) as BookDeleted
log.info("Deleting book [$bookDeleted]")
bookSuccessfulyDeleted.set(true)
}
AtomicBoolean bookSuccessfulyDeleted = new AtomicBoolean(false)
}

View File

@@ -0,0 +1,14 @@
package io.codearte.accurest.samples.spring
import com.fasterxml.jackson.annotation.JsonCreator
import groovy.transform.CompileStatic
@CompileStatic
class BookReturned implements Serializable {
String bookName
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
BookReturned(String bookName) {
this.bookName = bookName
}
}

View File

@@ -0,0 +1,40 @@
package io.codearte.accurest.samples.spring
import groovy.transform.CompileStatic
import groovy.util.logging.Slf4j
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.jms.core.JmsTemplate
import org.springframework.jms.core.MessageCreator
import org.springframework.stereotype.Service
import javax.jms.JMSException
import javax.jms.Message
import javax.jms.Session
@Service
@CompileStatic
@Slf4j
class BookService {
@Autowired JmsTemplate jmsTemplate
/**
Scenario for "should generate tests triggered by a method":
client side: must have a possibility to "trigger" sending of a message to the given messageFrom
server side: will run the method and await upon receiving message on the output messageFrom
Method triggers sending a message to a source
*/
void returnBook(BookReturned bookReturned ) {
log.info("Returning book [$bookReturned]")
MessageCreator messageCreator = new MessageCreator() {
@Override
public Message createMessage(Session session) throws JMSException {
Message message = session.createObjectMessage(bookReturned);
message.setStringProperty('BOOK-NAME', bookReturned.bookName)
return message
}
};
jmsTemplate.send('output', messageCreator)
}
}

View File

@@ -0,0 +1,14 @@
package io.codearte.accurest.samples.spring
import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.jms.annotation.EnableJms
@SpringBootApplication
@EnableJms
class SpringMessagingApplication {
static void main(String[] args) {
SpringApplication.run(SpringMessagingApplication.class, args)
}
}

View File

@@ -0,0 +1,143 @@
package io.codearte.accurest.samples.spring
import com.fasterxml.jackson.databind.ObjectMapper
import com.jayway.jsonpath.DocumentContext
import com.jayway.jsonpath.JsonPath
import com.toomuchcoding.jsonassert.JsonAssertion
import io.codearte.accurest.dsl.GroovyDsl
import io.codearte.accurest.messaging.AccurestMessage
import io.codearte.accurest.messaging.AccurestMessaging
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.SpringApplicationContextLoader
import org.springframework.test.context.ContextConfiguration
import spock.lang.Specification
import spock.util.concurrent.PollingConditions
import javax.inject.Inject
/**
* SPIKE ON TESTS FROM NOTES IN MessagingSpec
*/
// Context configuration would end up in base class
@ContextConfiguration(classes = [SpringMessagingApplication], loader = SpringApplicationContextLoader)
public class SpringApplicationSpec extends Specification {
// ALL CASES
@Inject AccurestMessaging accurestMessaging
ObjectMapper accurestObjectMapper = new ObjectMapper()
def "should work for triggered based messaging"() {
given:
def dsl = GroovyDsl.make {
label 'some_label'
input {
triggeredBy('bookReturnedTriggered()')
}
outputMessage {
sentTo('output')
body('''{ "bookName" : "foo" }''')
headers {
header('BOOK-NAME', 'foo')
}
}
}
// generated test should look like this:
when:
bookReturnedTriggered()
then:
def response = accurestMessaging.receiveMessage('output')
response.headers.get('BOOK-NAME') == 'foo'
and:
DocumentContext parsedJson = JsonPath.parse(accurestObjectMapper.writeValueAsString(response.payload))
JsonAssertion.assertThat(parsedJson).field('bookName').isEqualTo('foo')
}
def "should generate tests triggered by a message"() {
given:
def dsl = GroovyDsl.make {
label 'some_label'
input {
messageFrom('input')
messageBody([
bookName: 'foo'
])
messageHeaders {
header('sample', 'header')
}
}
outputMessage {
sentTo('output')
body([
bookName: 'foo'
])
headers {
header('BOOK-NAME', 'foo')
}
}
}
// generated test should look like this:
//given:
AccurestMessage inputMessage = accurestMessaging.create(
accurestObjectMapper.writeValueAsString([bookName: 'foo']),
[sample: 'header']
)
when:
accurestMessaging.send(inputMessage, 'input')
then:
def response = accurestMessaging.receiveMessage('output')
response.headers.get('BOOK-NAME') == 'foo'
and:
DocumentContext parsedJson = JsonPath.parse(accurestObjectMapper.writeValueAsString(response.payload))
JsonAssertion.assertThat(parsedJson).field('bookName').isEqualTo('foo')
}
def "should generate tests without destination, triggered by a message"() {
given:
def dsl = GroovyDsl.make {
label 'some_label'
input {
messageFrom('delete')
messageBody([
bookName: 'foo'
])
messageHeaders {
header('sample', 'header')
}
assertThat('bookWasDeleted()')
}
}
// generated test should look like this:
//given:
AccurestMessage inputMessage = accurestMessaging.create(
accurestObjectMapper.writeValueAsString([bookName: 'foo']),
[sample: 'header']
)
when:
accurestMessaging.send(inputMessage, 'delete')
then:
noExceptionThrown()
bookWasDeleted()
}
// BASE CLASS WOULD HAVE THIS:
@Autowired BookService bookService
@Autowired BookListener bookListener
void bookReturnedTriggered() {
bookService.returnBook(new BookReturned("foo"))
}
PollingConditions pollingConditions = new PollingConditions()
void bookWasDeleted() {
pollingConditions.eventually {
assert bookListener.bookSuccessfulyDeleted.get()
}
}
}

Some files were not shown because too many files have changed in this diff Show More