1

I am trying to write unit tests for a camel route - its for importing and processing a file

from(fullImportFTP)
        .routeId(STUB_FILE_DOWNLOAD_ROUTE_ID)
        .onException(Exception.class)
        .handled(false)
        .log(LoggingLevel.ERROR, STUB_IMPORT_ERROR_CODE)
        .end()
        .log("Processing  Stub file:[${header.CamelFileName}]")
        .to(ROUTE_TO_MACE);

from(ROUTE_TO_MACE)
        .routeId(STUB_FILE_IMPORT_ROUTE_ID)
        .onException(Exception.class)
        .handled(false)
        .log(LoggingLevel.ERROR, STUB_IMPORT_ERROR_CODE)
        .end()
        .onException(IOException.class)
        .maximumRedeliveries(routesConfig.camelMaximumRetries).redeliveryDelay(routesConfig.camelRedeliveryDelay)
        .handled(false)
        .log(LoggingLevel.ERROR, STUB_IMPORT_ERROR_CODE)
        .end()
        .split().tokenizeXML(ITEM).streaming()
        .process(processor)
        .to("log:route.StubRoute?level=DEBUG")
        .end()
        .log("Stub file sucessfully processed:[${header.CamelFileName}]");

And below is the unit test:

@RunWith(CamelSpringBootRunner.class)
@SpringBootTest
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
public class CamelRouteTest {
    @EndpointInject(uri = "mock:success_result")
    private MockEndpoint successResultEndpoint;

    @EndpointInject(uri = "direct:mock-import-stub-download")
    private FluentProducerTemplate producer;

    @Autowired
    private CamelContext camelContext;

    @MockBean
    RestTemplate restTemplate;


    private static final String MOCK_IMPORT_STUB_DOWNLOAD = "direct:mock-import-stub-download";
    private static final String TEST_STUB_FILE_LOCATION = "src/test/resources";

    @Before
    public void setup() throws Exception {
        camelContext.getRouteDefinition(STUB_FILE_DOWNLOAD_ROUTE_ID).autoStartup(true).adviceWith(camelContext,
                new AdviceWithRouteBuilder() {
                    @Override
                    public void configure() throws Exception {
                        replaceFromWith(MOCK_IMPORT_STUB_DOWNLOAD);
                        interceptSendToEndpoint("log:route.StubRoute?level=DEBUG").skipSendToOriginalEndpoint().to(successResultEndpoint);
                    }
                });

        camelContext.start();
    }

    @Test
    public void testFileDownloadRouter() throws Exception {
        File file = new File(TEST_STUB_FILE_LOCATION + "/Stub_11092018_162149_59642501.xml");
        successResultEndpoint.expectedMessageCount(1);
        producer.withBody(file).withHeader(Exchange.FILE_NAME, "Stub_24102018_162149_59642501.xml").send();
        successResultEndpoint.assertIsSatisfied();                                                                                                                                                                                                
    }

I always get the message count as 0. Here is the ERROR

java.lang.AssertionError: mock://success_result Received message count. Expected: <1> but was: <0> Expected :<1> Actual :<0>

What am I doing wrong here? I have 2 routes as you can see - the first one actually goes to the second one, so in the unit tests should I have 2 routes too? I haven't added 2 routes because if I debug I can see that it actually goes through the processor and returning the correct result.

ljs
  • 495
  • 1
  • 8
  • 23

1 Answers1

1

First of all: you are using AdviceWith, so you should put the annotation @UseAdviceWith on your testclass. Otherwise the automatic start of the Camel context and the route advice could overlap.

For the missing message on the Mock: Perhaps your test just asserts too early. I guess the producer does not block while the message is processed, but the MockEndpoint assert follows immediately after sending the message. Right after sending the message the received message count is still 0.

To check if waiting helps, you could insert a Thread.sleep(). If it works, you should get rid of the Thread.sleep() and replace it with a Camel NotifyBuilder

Just saw another point. The final to() in your interceptSendToEndpoint chain points to the MockEndpoint instance variable. I think this should point to the MockEndpoint URI, i.e. .to("mock:success_result")

And even one more: you get the first route to advice with getRouteDefinition(STUB_FILE_DOWNLOAD_ROUTE_ID) but in this advice block you advice both routes. That is probably the reason for your problem. The second route is not adviced and therefore your mock is not in place. You have to advice the second route in its own advice block.

@Before
public void setup() throws Exception {
    camelContext.getRouteDefinition(STUB_FILE_DOWNLOAD_ROUTE_ID).autoStartup(true).adviceWith(camelContext, new AdviceWithRouteBuilder() {
        @Override
        public void configure() throws Exception {
            replaceFromWith(MOCK_IMPORT_STUB_DOWNLOAD);
        }
    });
    camelContext.getRouteDefinition(STUB_FILE_IMPORT_ROUTE_ID).autoStartup(true).adviceWith(camelContext, new AdviceWithRouteBuilder() {
        @Override
        public void configure() throws Exception {
            interceptSendToEndpoint("log:route.StubRoute?level=DEBUG").skipSendToOriginalEndpoint().to("mock:success_result");
        }
    });

    camelContext.start();
}
burki
  • 6,741
  • 1
  • 15
  • 31
  • I have added the @UseAdviceWith annotation and put a wait, but it still fails unfortunately.. – ljs Nov 01 '18 at 19:02
  • changed the interceptEndPoint too to the URI , fails again.. Don't know if this is of any use but I can see this in the logs - "camel.component.mock.MockEndpoint : Asserting: mock://success_result is satisfied" before the routes shutdown and the error message. – ljs Nov 01 '18 at 21:53
  • Yeah, this is logged when the assertion is checked. It does not mean that it is satisfied, it is like "Asserting now if mock is satisfied..." and then the error message is the result. – burki Nov 02 '18 at 08:03
  • Just to isolate the problem. Can you replace the log-statement with the mock-endpoint statically, i.e. change the code the way the interceptor should do and disable the interceptor? If it works then, the interceptor has a problem. If it still not works, the Mock endpoint does not work correctly. – burki Nov 02 '18 at 08:14
  • Just saw another one: your advice block references the first route. Therefore the second route is not adviced and your mock endpoint not in place. – burki Nov 02 '18 at 10:09
  • how do I do that? should I have 2 references? – ljs Nov 02 '18 at 22:28
  • 1
    You have to do two separate adviceWith blocks, see in my extended answer – burki Nov 05 '18 at 08:47