I am doing a simple unit test with Camel. All I want to do is to read JSON content from a file (under resources), send it to a Java class for validation – this is the route that I am trying to test. Whatever I do, the template (which I use to sendBody(json) is always null. Here is my code:
public class RouteTests extends CamelTestSupport { @EndpointInject(uri = "mock:result") protected MockEndpoint resultEndpoint; @Produce(uri = "direct:start") protected ProducerTemplate template; @Autowired JSONObject testJson; @Before public void setUp() throws Exception { try { final ObjectMapper objectmapper = new ObjectMapper(); final ClassLoader loader = Thread.currentThread().getContextClassLoader(); final InputStream stream = loader.getResourceAsStream("test.json"); testJson = new JSONObject ((Map)objectmapper.readValue(stream, Map.class)); // Start Camel context = new DefaultCamelContext(); context.addRoutes(createRouteBuilder()); context.start(); } catch (IOException e) { } } @Test public void testSendMatchingMessage() throws Exception { //resultEndpoint.expectedBodiesReceived(expectedBody); resultEndpoint = getMockEndpoint("mock:result"); //resultEndpoint = context.getEndpoint("mock:result", MockEndpoint.class); resultEndpoint.expectedMessageCount(1); template.sendBody("direct:start", testJson); resultEndpoint.assertIsSatisfied(); } @Override protected RouteBuilder createRouteBuilder() { return new RouteBuilder() { public void configure() { from("direct:start") .filter().method(ValidationProcessor.class, "validate") .to("mock:result"); } }; } @Override protected JndiRegistry createRegistry() throws Exception { JndiRegistry jndi = super.createRegistry(); jndi.bind("ValidationProcessor", new ValidationProcessor", ()); return jndi; } }
Problems I faced:
Initially the result end point also was always null. (I used FilterTest.java for reference). Then I had to do an explicit
resultEndpoint = getMockEndpoint("mock:result");
to resolve that.
Then I read that I had to override the createRegistry, but I did not know how to bind. I just used the name of my validation class, but I don’t know if this is right.
But the template is always null. The null pointer exception (NPE) is at
template.sendBody("direct:start", testJson);
Please also point me to some reading if necessary. The reference code that Apache Camel documentation link to did not even have the starting of the Camel that I do in the setUp method.
Advertisement
Answer
I think you’ve missed out on a lot of the really helpful stuff that CamelTestSupport
does for you. It has its own setUp
method that you should override. I believe your test should really look something like this:
public class RouteTests extends CamelTestSupport { private JSONObject testJson; @Override public void setUp() throws Exception { // REALLY important to call super super.setUp(); ObjectMapper objectmapper = new ObjectMapper(); ClassLoader loader = Thread.currentThread().getContextClassLoader(); InputStream stream = loader.getResourceAsStream("test.json"); testJson = new JSONObject(objectmapper.readValue(stream, Map.class)); } @Override protected RouteBuilder createRouteBuilder() { return new RouteBuilder() { @Override public void configure() { from("direct:start") .filter().method(ValidationProcessor.class, "validate") .to("mock:result"); } }; } @Test public void testSendMatchingMessage() throws Exception { MockEndpoint resultEndpoint = getMockEndpoint("mock:result"); resultEndpoint.expectedMessageCount(1); template.sendBody("direct:start", testJson); resultEndpoint.assertIsSatisfied(); } }
Actually I would remove the override of setUp
altogether and put the reading of the test data in to the test method itself. Then it’s clear what the data is being used for and you can eliminate the testJson
field.
public class RouteTests extends CamelTestSupport { @Override protected RouteBuilder createRouteBuilder() { return new RouteBuilder() { @Override public void configure() { from("direct:start") .filter().method(ValidationProcessor.class, "validate") .to("mock:result"); } }; } @Test 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"); resultEndpoint.expectedMessageCount(1); template.sendBody("direct:start", testJson); resultEndpoint.assertIsSatisfied(); } }
There, much simpler.