Search code examples
javaunit-testingapache-camelspring-camel

Camel: How to mock a route with two endpoints


I'm new to Camel and I need to understand how to unit test my route that has two endpoints. The first endpoints gets a user ID and uses that for the second endpoint.

public RouteBuilder routeBuilder() {
    return new RouteBuilder() {
        @Override
        public void configure() throws HttpOperationFailedException {
            this.from(MyServiceConstant.ROUTE)
                    .setHeader(...)
                    .setHeader(...)
                    .to(MyConstants.THE_FIRST_ROUTE)
                    .setHeader(...)
                    .setHeader(...)
                    .process(...)
                    .setProperty(...)
                    .to(MyConstants.THE_SECOND_ROUTE)
        }
    };
}

So I have to mock both the MyConstants.THE_FIRST_ROUTE and MyConstants.THE_SECOND_ROUTE in my Test class. I did that but am not sure how to write the test. All I'm doing is hitting the second endpoint but don't know how to trigger the first.

@Produce(uri = MyServiceConstant.ROUTE)
private MyService myService;

@EndpointInject(uri = "mock:" + MyConstants.THE_FIRST_ROUTE)
private MockEndpoint mockFirstService;

@EndpointInject(uri = ""mock:" + MyConstants.THE_SECOND_ROUTE)
private MockEndpoint mockSecondService;

@Test
@DirtiesContext
public void getDetails()throws Exception {

    // **The missing part**: Is this the right way to call my first service? 
    this.mockFirstService.setUserId("123456");

    // this returns a JSON that I'll compare the service response to
    this.mockSecondService.returnReplyBody(...PATH to JSON file);

    UserDetail userDetailsInfo = this.myService.getUserDetails(...args)

    // all of my assertions
    assertEquals("First name", userDetailsInfo.getFirstName());

    MockEndpoint.assertIsSatisfied();
}

Solution

  • I got some time today to quickly hack around some demo code, with Camel Spring boot archetype. Here we go. My route produces messages from a timer component. Explicit delivery to an endpoint is not used.

    //Route Definition - myBean::saySomething() always returns String "Hello World"
    @Component
    public class MySpringBootRouter extends RouteBuilder {
    
        @Override
        public void configure() {
            from("timer:hello?period={{timer.period}}").routeId("hello_route")
                .transform().method("myBean", "saySomething")
                .to("log:foo")
                    .setHeader("test_header",constant("test"))
                .to("log:bar");
        }
    
    }
    
    
    @RunWith(CamelSpringBootRunner.class)
    @SpringBootTest
    public class MySpringBootRouterTest {
    
        @Autowired
        SpringCamelContext defaultContext;
    
        @EndpointInject("mock:foo")
        private MockEndpoint mockFoo;
        @EndpointInject("mock:bar")
        private MockEndpoint mockBar;
    
        @Test
        @DirtiesContext
        public void getDetails() throws Exception {
            assertNotNull(defaultContext);
            mockBar.expectedHeaderReceived("test_header", "test");
            mockBar.expectedMinimumMessageCount(5);
            MockEndpoint.setAssertPeriod(defaultContext, 5_000L);
            MockEndpoint.assertIsSatisfied(mockFoo, mockBar);
            mockFoo.getExchanges().stream().forEach( exchange -> assertEquals(exchange.getIn().getBody(),"Hello World"));
    
            //This works too
            //mockBar.assertIsSatisfied();
            //mockFoo.assertIsSatisfied();
        }
    
        @Before
        public void attachTestProbes() throws Exception {
            //This is Camel 3.0 API with RouteReifier
            RouteReifier.adviceWith(defaultContext.getRouteDefinition("hello_route"), defaultContext, new AdviceWithRouteBuilder() {
                @Override
                public void configure() throws Exception {
               //Hook into the current route, intercept log endpoints and reroute them to mock
                    interceptSendToEndpoint("log:foo").to("mock:foo");
                    interceptSendToEndpoint("log:bar").to("mock:bar");
                }
            });
        }
    
    }
    

    Warning to visitors from future: The test case here demonstrates how to intercept log: endpoints with mock: and set expectations on them. The test case may not be testing anything worthwhile.