0

I have a camel route which:

  1. polls a FTP server for new XML files
  2. downloads the files locally
  3. validates the XML files against a XSD
  4. splits the XML by categories into entities
  5. transforms the entities into json
  6. sends the json to a HTTP endpoint

UPDATE: This works now

@Component
public class FTPPoller extends RouteBuilder {
    XmlJsonDataFormat xmlJsonFormat = new XmlJsonDataFormat();

    @Override
    public void configure() throws Exception {

        from("{{endpoint.ftp.server}}")
                .id("ftp-poller")
                .log("Found file ${file:name}.")
                .to("{{endpoint.local.validation}}");


        from("{{endpoint.local.validation}}")
                .id("xml-validator")
                .log("Processing file ${file:name}.")
                .doTry()
                    .to("validator:classpath:schema/fr-masterdata.xsd")
                    .log("File ${file:name} is valid.")
                    .to("{{endpoint.local.processing}}")
                .doCatch(org.apache.camel.ValidationException.class)
                    .log("File ${file:name} is invalid.")
                    .to("{{endpoint.local.error}}")
                .end();

        from("{{endpoint.local.processing}}")
                .id("xml-processor")
                .split(xpath("//flu:entities/category")
                        .namespace("flu", "hxxx://www.xxx.com")
                ).streaming()
                .marshal(xmlJsonFormat)
                .to("direct:category")
                .end();

        from("direct:category")
                .id("requestbin")
                .log("Processing category ${body}")
                .setHeader(Exchange.HTTP_METHOD, constant("POST"))
                .setHeader(Exchange.CONTENT_TYPE, constant("application/json"))
                .to("{{endpoint.requestbin}}");

    }
}

Tests :

@RunWith(CamelSpringBootRunner.class)
@SpringBootTest(classes = {HbIntegrationApplication.class},
        properties = { "camel.springboot.java-routes-include-pattern=**/FTPPoller*"})
public class FTPPollerTest {

    @Autowired
    protected ProducerTemplate producerTemplate;

    @EndpointInject(uri = "{{endpoint.requestbin}}")
    protected MockEndpoint requestbinEndpoint;

    @EndpointInject(uri = "{{endpoint.local.error}}")
    protected MockEndpoint localErrorEndpoint;

    @Before
    public void cleanDir() throws Exception {
        deleteDirectory("hb");
    }


    @Test
    @DirtiesContext
    public void testFileUploadSuccess() throws Exception {
        String fileContent = FileUtils.readFileToString(new File("src/test/resources/test-files/category.xml"));

        requestbinEndpoint.expectedMessageCount(2);
        producerTemplate.sendBody("file://hb/incoming", fileContent);

        requestbinEndpoint.assertIsSatisfied();
    }

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

        localErrorEndpoint.expectedMessageCount(1);
        requestbinEndpoint.expectedMessageCount(0);

        producerTemplate.sendBody("file://hb/incoming", "invalidContent");

        localErrorEndpoint.assertIsSatisfied();
        requestbinEndpoint.assertIsSatisfied();
    }
}

application.properties :

endpoint.ftp.server=file://hb/incoming
endpoint.local.validation=file://hb/validation
endpoint.local.processing=file://hb/processing
endpoint.local.error=mock:file://hb/error
endpoint.requestbin=mock:requestbin

Remaining question is:

If I have defined the following property:

endpoint.local.processing=mock:file://hb/processing

my test fails with:

Caused by: java.lang.UnsupportedOperationException: You cannot consume from this endpoint

Is there any way to define which routes should be included in my Unit test?

Yann39
  • 14,285
  • 11
  • 56
  • 84
eistropfen
  • 35
  • 6
  • 1
    Why are you asking about 2 contexts? You are expecting to retrieve 2 and getting 0? Claus's answer below is correct in that you need to specify the expected before the sending. Finally. Are you restricting the files by filename on the from route? If not then I guess it would be a case of finding where it fails in the chain then analysing that – user3206236 Sep 17 '17 at 10:11

1 Answers1

0

You need to set the expectations on the mocks before you send data into Camel, eg this code

    localValidationEndpoint.sendBody(xml);

    requestbinEndpoint.expectedMessageCount(2);
    requestbinEndpoint.assertIsSatisfied();

Should be

    requestbinEndpoint.expectedMessageCount(2);

    localValidationEndpoint.sendBody(xml);

    requestbinEndpoint.assertIsSatisfied();
Claus Ibsen
  • 56,060
  • 7
  • 50
  • 65
  • Thank you Claus. I've already tried this with the same result. I think the issue is that 2 contexts are loaded (DefaultCamelContext and SpringCamelContext). What Annoations / config should be used for a Spring Boot / Apache Camel application that uses Annotations? – eistropfen Sep 15 '17 at 12:08
  • Camel in Action 2nd edition book has a chapter on testing with Camel and Spring Boot, and its source code has examples too. Otherwise you can check out camel-spring-boot source code and its unit tests how it does it. – Claus Ibsen Sep 16 '17 at 08:20
  • Thanks Claus. I've modified the code according to your sample but the test case still fails, whereas the application itself runs fine. I've added the detailed logs above. I've only recently started to use Camel for a POC (vs. Spring Integration) and so far I tend towards Camel, however Unit testing seems to be not as straight forward? Can I write a Unit test across multiple routes? e.g. send a file to the {{endpoint.ftp.server}} endpoint and verify that 2 messages have been received at the {{endpoint.requestbin}} endpoint? – eistropfen Sep 18 '17 at 00:01
  • I suggest to pickup a copy of my book Camel in Action 2nd edition and read the testing chapter. If not then try to re-read the testing docs on the website (albeit not as detailed and well structured as in the book). Also look at the unit tests of camel source code itself to get inspiration of testing. – Claus Ibsen Sep 18 '17 at 06:39
  • And yes you can certainly test with multiple routes. For more advanced testing read about advice-with testing. – Claus Ibsen Sep 18 '17 at 06:40
  • thanks Claus. I've actually bought a copy yesterday. looking forward to the final version. – eistropfen Sep 18 '17 at 23:34