CamelTestSupport with routes using classes with @Autowired

After help from experts over at camel unit test with cametestsupport, template is always null, I ended up with one more issue. Below is my test class - a simple test that tests a route which has only ValidationProcessor POJO.

public class RouteTests extends CamelTestSupport {

    protected RouteBuilder createRouteBuilder() {
        return new RouteBuilder() {
            public void configure() {
                        .filter().method(ValidationProcessor.class, "validate")

    public void testSendMatchingMessage() throws Exception {
        ObjectMapper objectmapper = new ObjectMapper();
        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        InputStream stream = loader.getResourceAsStream("test.json");
        JSONObject testJson = new JSONObject(objectmapper.readValue(stream, Map.class));

        MockEndpoint resultEndpoint = getMockEndpoint("mock:result");
        template.sendBody("direct:start", testJson);

The problem comes when this ValidationProcessor has an @Autowired component in it. My validation method needs data from Elasticsearch and hence I have an @Autowired for an elastic client. When I run mvn clean test, I am getting a NullPointerException stating that this elastic client is null. I think the issue is that this test is devoid of anything to do with Spring and hence the issue, but I do not know how to overcome this. My test needs to fetch data from Elasticsearch and hence the ValidationProcessor POJO does need @Autowired.

3 answers

  • answered 2018-03-13 21:58 Makoto

    What I've discovered is that it's unwise to extend CamelTestSupport when you want to use anything with Spring. In fact, there's a better way to do it - use the CamelSpringBootRunner instead.

    Well...I say "better". You're going to find yourself attaching a ton of annotations. Of the things you'll need:

    • A boostrapper to ensure that you're bootstrapping Camel correctly
    • The routes you wish to add to the classpath (and all of the beans); this ensures that they get added to Camel's registry through Spring's registry
    • You have to dirty the context after every run or your tests get into a wonky state.
    • You can automock endpoints by specifying either @MockEndpoints or @MockEndpointsAndSkip. The former sends the data along to the actual route.

    Below is just a start. Many of these annotations and their documentation can be found in the formal docs.

    @SpringBootTest(classes = { YourEntryPointClass.class })
    @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
    public class RouteTests {

  • answered 2018-03-14 06:57 Claus Ibsen

    When you extend CamelTestSupport then its NOT a spring application. You need to extend CamelSpringTestSupport. That would create Camel in a Spring runtime, and then allow beans to have IoC via Spring. This kind of testing is often used with Camel XML routes where the routes are defined in XML files. However you can have a plain XML file and refer to routes in Java DSL as well.

    However as Makoto answers then vanilla Spring unit testing is of late often about using all those gazillion annotations. Camel has support for that as well as his answer shows. This is also how for example Spring Boot testing is done etc.

    You can find some unit tests in camel-test-spring you can use as inspiration as well.

  • answered 2018-03-14 09:32 Phanindra Gopishetty

    your test class must extend CamelSpringTestSupport and annotated with @ContextConfiguration. Use classes or locations attribute of this annotation so that spring knows from where to load the dependent beans.