Testing with Apache Camel

Updated:

Today I want to talk about testing. (Crowd runs away screaming)

It’s a topic that comes up pretty often, but it’s not so easy with Camel. Or, should I say, it’s quite different with Camel.

The answer sometimes seems to be to write tests that are completely worthless, or just write none at all. Neither approach is good!

Camel testing checklist

I thought it was worth sharing my own personal approach towards writing tests in Camel:

  • Start by dividing complex routes down into smaller routes and join them together, using Direct endpoints or similar. This will make it easier for you to test your business logic in isolation.

    For example - with the route below, we can just test the processCustomer route in isolation without having to worry about the web service:

    from("direct:start")
        .split()
        .to("direct:processCustomer")
        .to("http://example.com/webservice")
        .to("file:customers/processed");
    
    // Now we can more easily test this route
    from("direct:processCustomer")
        .bean(ProcessCustomer.class);
    
  • Replace endpoints with mocks - mock endpoints really give you superpowers. They come with all sorts of APIs to test whether a message has arrived, whether it matches certain criteria, whether messages have arrived in the right order… You could write all these tests yourself, or you could just use mocks. Seriously, use mocks.

    This quick example shows what’s possible using just a small portion of the API. It’s easy to read, and very quick to write:

    MockEndpoint mock = getMockEndpoint("mock:result");
    mock.expectedMessageCount(1);
    mock.expectedBodiesReceived("Hello, world!");
      
    // Verify that the right message arrived within 60 seconds
    assertMockEndpointsSatisfied(60, TimeUnit.SECONDS);
    

    And how do you put mocks in your routes without rewriting your actual route code? Well…

  • Make your endpoints configurable - instead of hard-coding endpoint URIs in your routes, replace them with placeholders. This gives you so much more flexibility to be able to replace your endpoints with anything you like at testing time. This is an ideal way of throwing mock endpoints into your routes.

    If you’re using Spring Boot, this is very easy. For example, in the route below, I’ve made the from and to endpoints as placeholders:

    from("{{uri.from}}")
        .bean(MyCustomBean.class)
        .to("{{uri.to}}");
    

    Then, in your test class, you can replace these with whatever endpoints you like:

    @SpringBootTest(classes = YourApplication.class, properties = {
        "uri.from = direct:start",
        "uri.to   = mock:output" })
    
  • Test your logic, not endpoints - write tests to verify that your logic works as expected – for example, that a customer is flagged correctly based on their loyalty status, or that your order validation works. Probably don’t test that you can send an email or you can move files from one place to another.

  • Write an additional test whenever you fix a bug or find an edge case - use bug fixing as an opportunity to write a new test, so that the same bug cannot be reintroduced.

    @Test
    public void testCustomerWithNoAddressIsRejected() {
      //...write stuff here
    }
    
  • Don’t write tests that solely test Camel components - for example, we already know that Camel’s File component can write files. This doesn’t need to be tested again by you. :) Better to focus on testing your own business logic.

Have you got your own approach to testing Camel routes? Share it in the comments!

Leave a Comment