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