Accurest Messaging
| Feature available since {messaging_version} |
Accurest allows you to verify your application that uses messaging as means of communication. All of our integrations are working with Spring but you can also set one yourself.
Integrations
You can use one of the three integration configurations:
-
Apache Camel
-
Spring Integration
-
Spring Cloud Stream
If you’re using Spring Boot, the aforementioned test configurations will be appended automatically.
You have to provide as a dependency one of the Accurest Messaging modules. Example for Gradle:
// for Apache Camel
testCompile "io.codearte.accurest:accurest-messaging-camel:${accurestVersion}"
// for Spring Integration
testCompile "io.codearte.accurest:accurest-messaging-integration:${accurestVersion}"
// for Spring Cloud Stream
testCompile "io.codearte.accurest:accurest-messaging-stream:${accurestVersion}"
Manual Integration
The accurest-messaging-core module contains 3 main interfaces:
-
AccurestMessage- describes a message received / sent to a channel / queue / topic etc. -
AccurestMessageBuilder- describes how to build a message -
AccurestMessaging- class that allows you to build, send and receive messages -
AccurestFilter- interface to filter out the messages that do not follow the pattern from the DSL
In the generated test the AccurestMessaging is injected via @Inject annotation thus you can use other injection
frameworks than Spring.
You have to provide as a dependency the accurest-messaging-core module. Example for Gradle:
testCompile "io.codearte.accurest:accurest-messaging-core:${accurestVersion}"
Publisher side test generation
Having the input or outputMessage sections in your DSL will result in creation of tests on the publisher’s side. By default
JUnit tests will be created, however there is also a possibility to create Spock tests.
There are 3 main scenarios that we should take into consideration:
-
Scenario 1: there is no input message that produces an output one. The output message is triggered by a component inside the application (e.g. scheduler)
-
Scenario 2: the input message triggers an output message
-
Scenario 3: the input message is consumed and there is no output message
Scenario 1 (no input message)
For the given contract:
def contractDsl = GroovyDsl.make {
label 'some_label'
input {
triggeredBy('bookReturnedTriggered()')
}
outputMessage {
sentTo('activemq:output')
body('''{ "bookName" : "foo" }''')
headers {
header('BOOK-NAME', 'foo')
}
}
}
The following JUnit test will be created:
'''
// when:
bookReturnedTriggered();
// then:
AccurestMessage response = accurestMessaging.receiveMessage("activemq:output");
assertThat(response).isNotNull();
assertThat(response.getHeader("BOOK-NAME")).isEqualTo("foo");
// and:
DocumentContext parsedJson = JsonPath.parse(accurestObjectMapper.writeValueAsString(response.getPayload()));
assertThatJson(parsedJson).field("bookName").isEqualTo("foo");
'''
And the following Spock test would be created:
'''
when:
bookReturnedTriggered()
then:
def response = accurestMessaging.receiveMessage('activemq:output')
assert response != null
response.getHeader('BOOK-NAME') == 'foo'
and:
DocumentContext parsedJson = JsonPath.parse(accurestObjectMapper.writeValueAsString(response.payload))
assertThatJson(parsedJson).field("bookName").isEqualTo("foo")
'''
Scenario 2 (output triggered by input)
For the given contract:
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')
}
}
}
The following JUnit test will be created:
'''
// 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).isNotNull();
assertThat(response.getHeader("BOOK-NAME")).isEqualTo("foo");
// and:
DocumentContext parsedJson = JsonPath.parse(accurestObjectMapper.writeValueAsString(response.getPayload()));
assertThatJson(parsedJson).field("bookName").isEqualTo("foo");
'''
And the following Spock test would be created:
"""\
given:
def inputMessage = accurestMessaging.create(
'''{"bookName":"foo"}''',
['sample': 'header']
)
when:
accurestMessaging.send(inputMessage, 'jms:input')
then:
def response = accurestMessaging.receiveMessage('jms:output')
assert response !- null
response.getHeader('BOOK-NAME') == 'foo'
and:
DocumentContext parsedJson = JsonPath.parse(accurestObjectMapper.writeValueAsString(response.payload))
assertThatJson(parsedJson).field("bookName").isEqualTo("foo")
"""
Scenario 3 (no output message)
For the given contract:
def contractDsl = GroovyDsl.make {
label 'some_label'
input {
messageFrom('jms:delete')
messageBody([
bookName: 'foo'
])
messageHeaders {
header('sample', 'header')
}
assertThat('bookWasDeleted()')
}
}
The following JUnit test will be created:
'''
// given:
AccurestMessage inputMessage = accurestMessaging.create(
"{\\"bookName\\":\\"foo\\"}"
, headers()
.header("sample", "header"));
// when:
accurestMessaging.send(inputMessage, "jms:delete");
// then:
bookWasDeleted();
'''
And the following Spock test would be created:
'''
given:
def inputMessage = accurestMessaging.create(
\'\'\'{"bookName":"foo"}\'\'\',
['sample': 'header']
)
when:
accurestMessaging.send(inputMessage, 'jms:delete')
then:
noExceptionThrown()
bookWasDeleted()
'''
Consumer Stub Side generation
Unlike the HTTP part - in Messaging we need to publish the Groovy DSL inside the JAR with a stub. Then it’s parsed on the consumer side and proper stubbed routes are created.
For more infromation please consult the Stub Runner Messaging sections.
Gradle Setup
Example of Accurest Gradle setup:
ext {
contractsDir = file("mappings")
stubsOutputDirRoot = file("${project.buildDir}/production/${project.name}-stubs/")
wireMockStubsOutputDir = file(new File(stubsOutputDirRoot, 'repository/mappings/'))
contractsOutputDir = file(new File(stubsOutputDirRoot, 'repository/accurest/'))
}
task copyContracts(type: Copy) {
from contractsDir
include '**/*.groovy'
into contractsOutputDir
}
task stubsJar(type: Jar, dependsOn: ["generateWireMockClientStubs", copyContracts]) {
baseName = "${project.name}"
classifier = "stubs"
from stubsOutputDirRoot
}
artifacts {
archives stubsJar
}
publishing {
publications {
stubs(MavenPublication) {
artifactId "${project.name}-stubs"
artifact stubsJar
}
}
}
Maven Setup
Example of Maven can be found in the Accurest Maven Plugin README