Unit testing processors and Bean Bindings

When developing complex Processor implementations, it is useful to test them in isolation to ensure that they are fully exercised—something that may not necessarily be straightforward in a production route. Likewise, when developing Java classes marked with Camel annotations for bean binding, you want to check the binding logic as well as logic contained within the class. This recipe presents an approach for testing these types of scenarios.

Getting ready

The Java code for this recipe is located in the org.camelcookbook.examples.testing.exchange package.

How to do it...

Processors are typically used for composite actions that involve modifying the body of an exchange as well as a number of headers. Here is a Processor implementations process() method that we would like to test:

@Override
public void process(Exchange exchange) throws Exception {
  final String something = "SOMETHING";
  Message in = exchange.getIn();
  String action = in.getHeader("action", String.class);
  if ((action == null) || (action.isEmpty())) {
    in.setHeader("actionTaken", false);
  } else {
    in.setHeader("actionTaken", true);
    String body = in.getBody(String.class);
    if (action.equals("append")) {
    in.setBody(body + " " + something);
    } else if (action.equals("prepend")) {
      in.setBody(something + " " + body);
    } else {
      throw new IllegalArgumentException(
          "Unrecognized action requested: [" + action + "]");
    }
  }
}

In order to test this processor with an Exchange instance, perform the following steps:

  1. Extend CamelTestSupport and define an inline route through a RouteBuilder implementation that contains only that processor:
    @Override
    protected RouteBuilder createRouteBuilder()
        throws Exception {
      return new RouteBuilder() {
        @Override
        public void configure() throws Exception {
          from("direct:in")
            .process(new ComplicatedProcessor())
            .to("mock:out");
        }
      };
    }
  2. Test the route as usual:
    @Test
    public void testPrepend() throws Exception {
      MockEndpoint mockOut = getMockEndpoint("mock:out");
      mockOut.message(0).body().isEqualTo("SOMETHING text");
      mockOut.message(0).header("actionTaken").isEqualTo(true);
    
      Map<String, Object> headers =
          new HashMap<String, Object>();
      headers.put("action", "prepend");
    
      template.sendBodyAndHeaders("direct:in",
                                  "text", headers);
    
      assertMockEndpointsSatisfied();
    }

How it works...

By developing a throwaway route, we have enabled the processor under test to be executed inside an actual Camel context. This allows us to feed sample messages to the processor inside the route using a ProducerTemplate instance, and check the results using a mock endpoint. This approach distances us from the details of constructing an Exchange object by hand, and instead uses Camel to do it for us.

There's more...

Camel allows you to invoke bean methods directly from your route via a bean(..) statement, without needing that you refer to any Camel APIs in the method being invoked. A mechanism called Bean Binding is used to map the contents of the exchange to your method parameters (see the Routing messages directly to a Java method recipe in Chapter 3, Routing to Your Code). Using this mechanism you can access any part of the exchange without relying on the Camel API directly by using Camel's runtime annotations on the method arguments. While the resulting POJO can be tested like any other object, in order to test the bindings, you need to instantiate the bean inside a route and test as done before.

See also

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.12.107.31