ljs
ljs

Reputation: 533

Writing unit tests for camel routes in a SpringBoot application - getting messageCount 0

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.

Upvotes: 1

Views: 3480

Answers (1)

burki
burki

Reputation: 7005

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();
}

Upvotes: 1

Related Questions