A previous article was focused on Apache Camel aggregation component, its new JDBC persistent repository more precisely. The sample provided includes a unit test which uses multiple good practices to test Camel routes. Let’s analyse them one by one.
Have a test spring context
The main idea is to keep unit test as simple as possible. External resources should not be involved. If required mock, in-memory database… should be used. Therefore a separate spring context has been created for tests.
This context imports the initial context and overrides components using external resources. This is the case for properties and endpoints.
|
1 2 3 4 |
(…) <!-- Import Production context --> <import resource="camel-context.xml" /> (…) |
Use properties for the endpoints URL
Most of the time endpoints URL need to be adapted to the environment. java.util.Properites is very useful for that. It can be initialized with values from a properties file. This file can be externalized or even provided by the environment, e.g. OSGi. In the sample, the Properties object is created in the context for simplicity’s sake. The production spring context looks like this:
|
1 2 3 4 5 6 7 8 |
<!-- Define Production endpoint URLs --> <util:properties id="spring-properties"> <prop key="in">file:target/in</prop> <prop key="out">file:target/out</prop> </util:properties> <camelContext id="CamelContext" xmlns="http://camel.apache.org/schema/spring" trace="true"> <propertyPlaceholder id="properties" location="ref:spring-properties" /> |
Notice that two propertyPlacerholder objects are created: one for spring and one for Camel. The Camel one simple refers to Spring’s one. This is required to use properties in endpoint URLs. Camel properties component is available since Camel 2.3.
The test context overrides the URLs and makes the endpoint independent of the file system.
|
1 2 3 4 5 |
<!-- Define test endpoint URLs --> <util:properties id="spring-properties"> <prop key="in">direct:in</prop> <prop key="out">log:out</prop> </util:properties> |
Perform test on production route
The more interesting element is that the test uses the production route. This was made possible since Camel 2.7 thanks to CAMEL-3578. The idea was to be able to create mock endpoints using existing endpoints automatically.
This functionality is disabled by default. The code snippets below show how to enable this new functionality using Java and Spring domain specific language (DSL).
JAVA
|
1 2 3 4 5 6 7 8 |
public class IsMockEndpointsJUnit4Test extends CamelTestSupport { @Override public String isMockEndpoints() { // override this method and return the pattern for which endpoints to mock. // use * to indicate all return "*"; } |
The returned value is the pattern of all the endpoints to mock as indicated in the comment.
XML
|
1 2 3 |
<bean id="mockAllEndpoints" class="org.apache.camel.impl.InterceptSendToMockEndpointStrategy"> <constructor-arg index="0" value="log*"/> </bean> |
With the XML DSL all endpoint are mocked by default. The constructor-arg shown in the example allows restricting the number of endpoints created like in Java. See the documentation for more details.
The endpoint can then be tested simply by prefixing the URL with mock: in the unit test.
|
1 |
MockEndpoint mock = getMockEndpoint("mock:" + endpoints.getProperty("out")); |
Conclusion
Camel 2.7 provides nice features to make unit testing easier. The best part is that the production routes can now be directly unit tested.