Stub Runner for Messaging
| Feature available since {messaging_version} |
Stub Runner has the functionality to run the published stubs in memory. It can integrate with the following frameworks out of the box
-
Spring Integration
-
Spring Cloud Stream
-
Apache Camel
It also provides points of entry to integrate with any other solution on the market.
Stub triggering
To trigger a message it’s enough to use the StubTigger interface:
package io.codearte.accurest.stubrunner
interface StubTrigger {
/**
* Triggers an event by a given label for a given {@code groupid:artifactid} notation. You can use only {@code artifactId} too.
*
* Feature related to messaging.
*
* @return true - if managed to run a trigger
*/
boolean trigger(String ivyNotation, String labelName)
/**
* Triggers an event by a given label.
*
* Feature related to messaging.
*
* @return true - if managed to run a trigger
*/
boolean trigger(String labelName)
/**
* Triggers all possible events.
*
* Feature related to messaging.
*
* @return true - if managed to run a trigger
*/
boolean trigger()
/**
* Returns a mapping of ivy notation of a dependency to all the labels it has.
*
* Feature related to messaging.
*/
Map<String, Collection<String>> labels()
}
For convenience the StubFinder interface extends StubTrigger so it’s enough to use only one in your tests.
StubTrigger gives you the following options to trigger a message:
Trigger by label
stubFinder.trigger('return_book_1')
Trigger by group and artifact ids
stubFinder.trigger('io.codearte.accurest.stubs:camelService', 'return_book_1')
Trigger by artifact ids
stubFinder.trigger('camelService', 'return_book_1')
Trigger all messages
stubFinder.trigger()
Stub Runner Messaging Camel
Accurest Stub Runner’s messaging module gives you an easy way to integrate with Apache Camel. For the provided artifacts it will automatically download the stubs and register the required routes.
Adding it to the project
To use it you have to add the following dependency to your project (example for Gradle):
testCompile "io.codearte.accurest:stub-runner-messaging-camel:${accurestVersion}"
Examples
Stubs structure
Let us assume that we have the following Maven repository with a deployed stubs for the
camelService application.
└── .m2
└── repository
└── io
└── codearte
└── accurest
└── stubs
└── camelService
├── 0.0.1-SNAPSHOT
│ ├── camelService-0.0.1-SNAPSHOT.pom
│ ├── camelService-0.0.1-SNAPSHOT-stubs.jar
│ └── maven-metadata-local.xml
└── maven-metadata-local.xml
And the stubs contain the following structure:
├── META-INF
│ └── MANIFEST.MF
└── repository
├── accurest
│ ├── bookDeleted.groovy
│ ├── bookReturned1.groovy
│ └── bookReturned2.groovy
└── mappings
Let’s consider the following contracts (let' number it with 1):
io.codearte.accurest.dsl.GroovyDsl.make {
label 'return_book_1'
input {
triggeredBy('bookReturnedTriggered()')
}
outputMessage {
sentTo('jms:output')
body('''{ "bookName" : "foo" }''')
headers {
header('BOOK-NAME', 'foo')
}
}
}
and number 2
io.codearte.accurest.dsl.GroovyDsl.make {
label 'return_book_2'
input {
messageFrom('jms:input')
messageBody([
bookName: 'foo'
])
messageHeaders {
header('sample', 'header')
}
}
outputMessage {
sentTo('jms:output')
body([
bookName: 'foo'
])
headers {
header('BOOK-NAME', 'foo')
}
}
}
Scenario 1 (no input message)
So as to trigger a message via the return_book_1 label we’ll use the StubTigger interface as follows
stubFinder.trigger('return_book_1')
Next we’ll want to listen to the output of the message sent to jms:output
Exchange receivedMessage = camelContext.createConsumerTemplate().receive('jms:output', 5000)
And the received message would pass the following assertions
receivedMessage != null
assertThatBodyContainsBookNameFoo(receivedMessage.in.body)
receivedMessage.in.headers.get('BOOK-NAME') == 'foo'
Scenario 2 (output triggered by input)
Since the route is set for you it’s enough to just send a message to the jms:output destination.
camelContext.createProducerTemplate().sendBodyAndHeaders('jms:input', new BookReturned('foo'), [sample: 'header'])
Next we’ll want to listen to the output of the message sent to jms:output
Exchange receivedMessage = camelContext.createConsumerTemplate().receive('jms:output', 5000)
And the received message would pass the following assertions
receivedMessage != null
assertThatBodyContainsBookNameFoo(receivedMessage.in.body)
receivedMessage.in.headers.get('BOOK-NAME') == 'foo'
Scenario 3 (input with no output)
Since the route is set for you it’s enough to just send a message to the jms:output destination.
camelContext.createProducerTemplate().sendBodyAndHeaders('jms:delete', new BookReturned('foo'), [sample: 'header'])
Stub Runner Messaging Integration
Accurest Stub Runner’s messaging module gives you an easy way to integrate with Spring Integration. For the provided artifacts it will automatically download the stubs and register the required routes.
Adding it to the project
To use it you have to add the following dependency to your project (example for Gradle):
testCompile "io.codearte.accurest:stub-runner-messaging-integration:${accurestVersion}"
Examples
Stubs structure
Let us assume that we have the following Maven repository with a deployed stubs for the
integrationService application.
└── .m2
└── repository
└── io
└── codearte
└── accurest
└── stubs
└── integrationService
├── 0.0.1-SNAPSHOT
│ ├── integrationService-0.0.1-SNAPSHOT.pom
│ ├── integrationService-0.0.1-SNAPSHOT-stubs.jar
│ └── maven-metadata-local.xml
└── maven-metadata-local.xml
And the stubs contain the following structure:
├── META-INF
│ └── MANIFEST.MF
└── repository
├── accurest
│ ├── bookDeleted.groovy
│ ├── bookReturned1.groovy
│ └── bookReturned2.groovy
└── mappings
Let’s consider the following contracts (let' number it with 1):
io.codearte.accurest.dsl.GroovyDsl.make {
label 'return_book_1'
input {
triggeredBy('bookReturnedTriggered()')
}
outputMessage {
sentTo('output')
body('''{ "bookName" : "foo" }''')
headers {
header('BOOK-NAME', 'foo')
}
}
}
and number 2
io.codearte.accurest.dsl.GroovyDsl.make {
label 'return_book_2'
input {
messageFrom('input')
messageBody([
bookName: 'foo'
])
messageHeaders {
header('sample', 'header')
}
}
outputMessage {
sentTo('output')
body([
bookName: 'foo'
])
headers {
header('BOOK-NAME', 'foo')
}
}
}
and the following Spring Integration Route:
<?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">
<!-- REQUIRED FOR TESTING -->
<bridge input-channel="output"
output-channel="outputTest"/>
<channel id="outputTest">
<queue/>
</channel>
</beans:beans>
Scenario 1 (no input message)
So as to trigger a message via the return_book_1 label we’ll use the StubTigger interface as follows
stubFinder.trigger('return_book_1')
Next we’ll want to listen to the output of the message sent to output
AccurestMessage receivedMessage = messaging.receiveMessage('outputTest')
And the received message would pass the following assertions
receivedMessage != null
assertJsons(receivedMessage.payload)
receivedMessage.headers.get('BOOK-NAME') == 'foo'
Scenario 2 (output triggered by input)
Since the route is set for you it’s enough to just send a message to the output destination.
messaging.send(new BookReturned('foo'), [sample: 'header'], 'input')
Next we’ll want to listen to the output of the message sent to output
AccurestMessage receivedMessage = messaging.receiveMessage('outputTest')
And the received message would pass the following assertions
receivedMessage != null
assertJsons(receivedMessage.payload)
receivedMessage.headers.get('BOOK-NAME') == 'foo'
Scenario 3 (input with no output)
Since the route is set for you it’s enough to just send a message to the input destination.
messaging.send(new BookReturned('foo'), [sample: 'header'], 'delete')
Stub Runner Messaging Stream
Accurest Stub Runner’s messaging module gives you an easy way to integrate with Spring Stream. For the provided artifacts it will automatically download the stubs and register the required routes.
In Stub Runner’s integration with Stream the messageFrom or sentTo Strings are resolved
first as a destination of a channel, and then if there is no such destination it’s resolved as a
channel name.
|
Adding it to the project
To use it you have to add the following dependency to your project (example for Gradle):
testCompile "io.codearte.accurest:stub-runner-messaging-stream:${accurestVersion}"
Examples
Stubs structure
Let us assume that we have the following Maven repository with a deployed stubs for the
streamService application.
└── .m2
└── repository
└── io
└── codearte
└── accurest
└── stubs
└── streamService
├── 0.0.1-SNAPSHOT
│ ├── streamService-0.0.1-SNAPSHOT.pom
│ ├── streamService-0.0.1-SNAPSHOT-stubs.jar
│ └── maven-metadata-local.xml
└── maven-metadata-local.xml
And the stubs contain the following structure:
├── META-INF
│ └── MANIFEST.MF
└── repository
├── accurest
│ ├── bookDeleted.groovy
│ ├── bookReturned1.groovy
│ └── bookReturned2.groovy
└── mappings
Let’s consider the following contracts (let' number it with 1):
io.codearte.accurest.dsl.GroovyDsl.make {
label 'return_book_1'
input {
triggeredBy('bookReturnedTriggered()')
}
outputMessage {
sentTo('returnBook')
body('''{ "bookName" : "foo" }''')
headers {
header('BOOK-NAME', 'foo')
}
}
}
and number 2
io.codearte.accurest.dsl.GroovyDsl.make {
label 'return_book_2'
input {
messageFrom('bookStorage')
messageBody([
bookName: 'foo'
])
messageHeaders {
header('sample', 'header')
}
}
outputMessage {
sentTo('returnBook')
body([
bookName: 'foo'
])
headers {
header('BOOK-NAME', 'foo')
}
}
}
and the following Spring configuration:
stubrunner.stubs.repository.root: classpath:m2repo/repository/
stubrunner.stubs.ids: io.codearte.accurest.stubs:streamService:0.0.1-SNAPSHOT:stubs
spring:
cloud:
stream:
bindings:
output:
destination: returnBook
input:
destination: bookStorage
Scenario 1 (no input message)
So as to trigger a message via the return_book_1 label we’ll use the StubTrigger interface as follows
stubFinder.trigger('return_book_1')
Next we’ll want to listen to the output of the message sent to a channel whose destination is returnBook
AccurestMessage receivedMessage = messaging.receiveMessage('returnBook')
And the received message would pass the following assertions
receivedMessage != null
assertJsons(receivedMessage.payload)
receivedMessage.headers.get('BOOK-NAME') == 'foo'
Scenario 2 (output triggered by input)
Since the route is set for you it’s enough to just send a message to the bookStorage destination.
messaging.send(new BookReturned('foo'), [sample: 'header'], 'bookStorage')
Next we’ll want to listen to the output of the message sent to returnBook
AccurestMessage receivedMessage = messaging.receiveMessage('returnBook')
And the received message would pass the following assertions
receivedMessage != null
assertJsons(receivedMessage.payload)
receivedMessage.headers.get('BOOK-NAME') == 'foo'
Scenario 3 (input with no output)
Since the route is set for you it’s enough to just send a message to the output destination.
messaging.send(new BookReturned('foo'), [sample: 'header'], 'delete')