Test that camel route
You might want to get a bit of context by reading the 2 first parts of this series.
This time, I’ll show you how a route is tested by using mock producers and consumers and setting up the expectations. As I always remind the team, this is unit testing, not integration testing. At this point, we need to trust that the Camel team has properly tested all it’s components. What we want to do is check that 1) our route is routing messages to the proper endpoints, and 2) our enrichers or filters are kicking in properly.
To better understand the rest of this post, reading through this might be usefull.
Route Builder modifications
In the previous example, I had hard coded all route and processor information directly into the RouteBuilder implementation.
Obviously, this won’t cut it if we want to test. So the first thing we want to do is externalize the routeconfiguration information to a class (backed by an interface. You’ll se why later).
class MyRouteBuilder extends RouteBuilder {
private IRouteBuilderConiguration config;
@Override
public void configure() throws Exception {
errorHandler(
deadLetterChannel(config.getDlqEndpointUrl()).
delay(config.getErrorHandlerDelay()).
maximumRedeliveries(config.getErrorHandlerRetries())
);
from(config.getSourceEndpointUrl()).
choice().
when(config.getMessageFilter()).
process(config.getMessageEnricher()).to(config.getMessageEndpointUrl()).
otherwise().to(config.getErrorEndpointUrl());
}
}
What’s missing here is a concrete implementation of the IRouteBuilderConfiguration interface. It would look something like:
public class MyRouteBuilderConfiguration implements IRouteBuilderConfiguration {
public String getMessageEndpointUrl() {
return ....
}
....
}
I used spring to inject the configuration into the builder, but you can use whatever you want.
<bean id="myRouteBuilder" class="default.MyRouteBuilder">
<property name="configuration">
<bean class="default.MyRouteBuilderConfiguration">
<property name="messageFilter" ref="myFilter"/>
<property name="messageEnricher" ref="myEnricher"/>
</bean>
</property>
</bean>
Test class
Once that’s done, then it’s simply a case of following what’s in the Camel testing example page with a few variations.
- Overide the createRouteBuilder() method, but make sure to send back your own implementation
- Inject a different IRouteBuilderConfiguration implementation which uses mock and direct endpoints.
For example:
public class TestMessageRouter extends CamelTestSupport {
private static final String SOURCE_COMPONENT_URL = "direct:start";
private static final String DLQ_COMPONENT_URL = "mock:dlq";
private static final String INVALID_COMPONENT_URL = "mock:invalid";
private static final String ENDPOINT_URL = "mock:endpoint";
@EndpointInject(uri = DLQ_COMPONENT_URL)
protected MockEndpoint dlqEndpoint;
@EndpointInject(uri = INVALID_COMPONENT_URL)
protected MockEndpoint invalidEndpoint;
@EndpointInject(uri = ENDPOINT_URL)
protected MockEndpoint endpoint;
@Produce(uri= SOURCE_COMPONENT_URL)
protected ProducerTemplate producerTemplate;
public void testMessageOk() throws Exception {
producerTemplate.sendBodyAndHeaders("a", getValidHeaders());
invalidEndpoint.expectedMessageCount(0);
dlqEndpoint.expectedMessageCount(0);
endpoint.expectedMessageCount(1);
dlqEndpoint.assertIsSatisfied();
invalidEndpoint.assertIsSatisfied();
endpoint.assertIsSatisfied();
Message inMessage = endpoint.getReceivedExchanges().get(0).getIn();
Assert.assertEquals("a", inMessage.getBody());
}
public void testWithInvalidBodyType() throws Exception {
Map<String, Object> headers =createValidHeaders();
producerTemplate.sendBodyAndHeaders(Integer.valueOf(1), headers);
invalidEndpoint.expectedMessageCount(1);
endpoint.expectedMessageCount(0);
dlqEndpoint.expectedMessageCount(0);
dlqEndpoint.assertIsSatisfied();
invalidEndpoint.assertIsSatisfied();
endpoint.assertIsSatisfied();
}
@Override
protected RouteBuilder createRouteBuilder() throws Exception {
MyRouteBuilder builder = new MyRouteBuilder();
builder.setConfiguration(new TestRunnerRouteConfiguration());
return builder;
}
class TestRunnerRouteConfiguration implements IRouteBuilderConfiguration {
public Endpoint getMessageEndpoint() {
return endpoint;
}
public String getDLQCompomentUrl() {
return DLQ_COMPONENT_URL;
}
public String getInvalidMessageComponentUrl() {
return INVALID_COMPONENT_URL;
}
public String getSourceComponentUrl() {
return SOURCE_COMPONENT_URL;
}
....
}
}
The example isn’t complete, but it does give a good idea of what can be done. The learning curve isn’t extremely steep with Camel, but it’s there and you most likely won’t pickup all the concepts immediately. We’re not talking weeks and days, just a few hours.
I guess that covers it for now. I’ll be looking to setup a Component that can publish to Tumblr, just as an excersise, so if I get around to that, I’ll post the results here.
| Print article |