nanosoft
nanosoft

Reputation: 3091

Testing camel routes

I have multiple routes classes defined in my project under com.comp.myapp.routes. For testing these I am mocking the end route and checking/comparing delivery received.

Say for example I have below routes:

public class MyRoute1 extends RouteBuilder {
    public void configure() throws Exception {
       //Route_1 code
    }
}

public class MyRoute2 extends RouteBuilder {
    public void configure() throws Exception {
       //Route_2 code
    }
}

....
...//some route impl
..
public class MyRouteN extends RouteBuilder {
    public void configure() throws Exception {
       //Route_N code
    }
}

Now for all these routes the test case that I wrote seems same. First mock it.

Mock for MyRoute1:

public class MyRoute1_Mock extends RouteBuilder {
    public void configure() throws Exception {
      from("direct:sampleInput")
                .log("Received Message is ${body} and Headers are ${headers}")
                .to("mock:output");
    }
}

Test for MyRoute1:

public class MyRoute1_Test extends CamelTestSupport {
    @Override
    public RoutesBuilder createRouteBuilder() throws Exception {
        return new MyRoute1_Mock();
    }
    @Test
    public void sampleMockTest() throws InterruptedException {
        String expected="Hello";
        /**
         * Producer Template.
         */
        MockEndpoint mock = getMockEndpoint("mock:output");
        mock.expectedBodiesReceived(expected);
        String input="Hello";
        template.sendBody("direct:sampleInput",input );
        assertMockEndpointsSatisfied();
    }
}

Now to make unit test for other classes just copy and paste the above code with different name say MyRoute2_Test , MyRoute3_Test , ...MyRouteN_Test.

So what did it actually tested? It's just written for the purpose of writing test case. It actually just checks/tests if mock library and camel-test library work or not Not our code works or not? How should it actually be done?

Upvotes: 5

Views: 11098

Answers (3)

burki
burki

Reputation: 7005

You want to test your Camel routes but in the test you mock them away. So yes, you are testing your route mock instead of the real route.

To test your real routes:

  • Send a message to your real routes from endpoint
  • If this is not easy, mock your from endpoint (not the entire route!) by replacing it with a direct endpoint. This is quite easy with adviceWith
  • The test message is going through your route
  • Assert that any to endpoint receives the correct message by mocking these endpoints too. Again, use adviceWith for that. And Camel Mock of course
  • You can get the received messages (Exchanges) from a Camel Mock to do in depth assertions
  • If you got the happy test, start to write negative tests by injecting errors in your route. adviceWith can help here too
  • ... and so on

If you are completely new to Camel route tests, get Camel in Action 2nd edition. It explains all mentioned testing aspects for Camel applications on 65 pages. And of course it also takes you on a complete ride through the Camel universe on much more pages.

By the way: if testing your routes is hard, they are too complex. Start to divide your routes so that they are easily testable.

Upvotes: 2

Hpalle
Hpalle

Reputation: 16

Explained in-line,Hope this helps you understand significance of Mock in Unit Test:

 public void sampleMockTest() throws InterruptedException {
    String expected="Hello"; 
    MockEndpoint mock = getMockEndpoint("mock:output");//Mocking endpoint
    mock.expectedBodiesReceived(expected); //Setting expected output to mocked endpoint
    String input="Hello";
    template.sendBody("direct:sampleInput",input );//triggering route execution by sending input to route
    assertMockEndpointsSatisfied(); //Verifies if input is equal to output
}

If your endpoint is Rest service you can make use of "TestRestTemplate" instead of Mocking it and Test like below:

import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class SampleCamelApplicationTest {
}
import org.springframework.boot.test.web.client.TestRestTemplate;

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class SampleCamelApplicationTest {
   @Autowired
   private TestRestTemplate restTemplate;
}
@Test
public void sayHelloTest() {
   // Call the REST API
   ResponseEntity<String> response = restTemplate.getForEntity("/camel/hello", String.class);
   assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
   String s = response.getBody();
   assertThat(s.equals("Hello World"));
}

Upvotes: 0

Steve Huston
Steve Huston

Reputation: 1590

The route you show doesn't really do anything to the messages traversing it, so testing that the same text you sent in one end comes out the other is all there is to test.

For routes with more data transformation and processing, you could test the output data types, that processors were called when needed, you could mock in throwing of exceptions, etc. What you have above is a good start on that.

Upvotes: 0

Related Questions