You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@camel.apache.org by me...@volny.cz on 2025/06/03 10:24:04 UTC

Camel Test Infrastructure FTP

Hello,

I would like to use Camel Infrastructure for my Spring Boot Camel End-to-End tests.

II have spent quite some time investigating how it works. Unfortunately the documentation is very limited and I was not able to find any examples either.

I started with a very simple scenario -> one route from FTP to file. After couple of hours I was able to come to following test that works.

@SpringBootTest
@Import({ FtpServiceTestConfig.class, Process1TestRoutes.class})
@TestPropertySource("classpath:application-e2e.yaml")
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@ActiveProfiles("e2e")
public class Process1E2ETest {
    @Autowired
    CamelContext camelContext;

    @RegisterExtension
    static FtpService ftpService = FtpServiceFactory.createEmbeddedService();

    @Test
    void shouldTransferFileFromInputToOutput() throws Exception {

        // Create the route after FTP server is initialized
        camelContext.addRoutes(new RouteBuilder() {
            @Override
            public void configure() {
                from("ftp://" + ftpService.hostname() + ":" + ftpService.port() + "/" + ftpService.directoryName()
                    + "?username=" + ftpService.username()
                    + "&password=" + ftpService.password()
                    + "&delete=true&delay=1000")
                    .to("file:target/out")
                    .log("Received: ${file:name}");
            }
        });

        // Ensure target directory exists
        Files.createDirectories(Path.of("target/out"));

        // Create input file in the correct FTP directory
        Path ftpRootDir = ftpService.getFtpRootDir();
        Path ftpInputDir = ftpRootDir.resolve(ftpService.directoryName());
        Files.createDirectories(ftpInputDir);
        Path inputFile = ftpInputDir.resolve("test.txt");
        Files.writeString(inputFile, "Hello from test", StandardOpenOption.CREATE);

        System.out.println("Created file at: " + inputFile.toAbsolutePath());

        // Wait longer for Camel route to process the file
        Thread.sleep(5000);

        Path outputFile = Path.of("target/out/test.txt");
        assertTrue(Files.exists(outputFile), "Output file should exist at " + outputFile.toAbsolutePath());
        String content = Files.readString(outputFile);
        assertEquals("Hello from test", content);
    }
}

I had to copy FtpService  and FtpServiceFactory with their dependencies from Camel Github Repository (https://github.com/apache/camel/tree/camel-4.12.x/test-infra/camel-test-infra-ftp/src/test/java/org/apache/camel/test/infra/ftp/services) as they are not included in maven dependency jar. I am using Apache Camel 4.12.0

I do not like the solution much as it creates the route only inside the test that is kind of ugly. If I try to create it in @TestConfiguration or even @BeforeAll the troube is that the FTP server is not initalized yet and ftpService.port() is 0 at that time.

Can anyone explain me how it is meant to be used and/or provide some example?

Regards

Jiří

Re: Camel Test Infrastructure FTP

Posted by Federico Mariani <fe...@gmail.com>.
I see, the problem is that in camel-ftp-test-infra the ftp server is
initialized() in a BeforeEach block, not a BeforeAll, this is why you do
not have it, but I think that you can easily extend FtpEmbeddedService and
override BeforeEach and BeforeAll, to something like this:

@Override
public void beforeAll(ExtensionContext extensionContext) {
    initExtensionContext(extensionContext);

    initialize();

}

@Override
public void afterAll(ExtensionContext extensionContext) {

    shutdown();
    this.context = null;
}

@Override
public void afterEach(ExtensionContext extensionContext) {
}

@Override
public void beforeEach(ExtensionContext extensionContext) {
    initExtensionContext(extensionContext); // Not sure this is needed..
}


I tried to do this in Camel but some tests need the server initialized
in BeforeEach block, this is why I am not going to change the
behaviour in Camel.


Regards,

Federico


Il giorno gio 5 giu 2025 alle ore 11:37 medved@volny.cz <me...@volny.cz>
ha scritto:

> Hi,
>
> thank you very much for your feedback. Type test-jar helped to include the
> test classes. I tried to replicate some test fro camel-spring-boot but I
> think I miss some important part to the puzzle. This is my test class
> derived from
> https://github.com/apache/camel-spring-boot/blob/main/components-starter/camel-ftp-starter/src/test/java/org/apache/camel/component/file/remote/springboot/ftp/FromFtpToBinaryFileTest.java
>
> I have just included the parent classes to make it compact.
>
>
> @DirtiesContext
> @CamelSpringBootTest
> @SpringBootTest(classes = {CamelAutoConfiguration.class,
> Process1E2ETest.class,
>     Process1E2ETest.TestConfiguration.class})
> // Baaed on FromFtpToBinaryFileIT
> public class Process1E2ETest {
>
>     @RegisterExtension
>     static FtpEmbeddedService service = new FtpEmbeddedService();
>
>     @Autowired
>     protected CamelContext context;
>
>     @Autowired
>     protected ProducerTemplate template;
>
>     @EndpointInject("mock:result")
>     private MockEndpoint resultEndpoint;
>
>     protected static void assertFileExists(String filename) {
>         File file = new File(filename);
>         assertTrue(file.exists(), "File " + filename + " should exist");
>         assertTrue(file.isFile(), "File " + filename + " should be a
> file");
>     }
>
>     protected static void assertFileNotExists(Path file) {
>         Assertions.assertFalse(
>             Files.exists(file, new LinkOption[0]), "File " + file + "
> should not exist");
>     }
>
>     protected static void assertFileExists(Path file, String content)
> throws IOException {
>         assertTrue(Files.exists(file, new LinkOption[0]), "File " + file +
> " should exist");
>         assertTrue(Files.isRegularFile(file, new LinkOption[0]),
>             "File " + file + " should be a file");
>         Assertions.assertEquals(content, new
> String(Files.readAllBytes(file)),
>             "File " + file + " has unexpected content");
>     }
>
>     public static Path testDirectory(Class<?> testClass, boolean create) {
>         Path dir = Paths.get("target", "data", testClass.getSimpleName());
>         if (create) {
>             try {
>                 Files.createDirectories(dir);
>             } catch (IOException var4) {
>                 throw new IllegalStateException("Unable to create test
> directory: " + dir, var4);
>             }
>         }
>
>         return dir;
>     }
>
>     // must user "consumer." prefix on the parameters to the file component
>     private String getFtpUrl() {
>         return "ftp://admin@localhost:" + getPort() +
> "/tmp4/camel?password=admin&binary=true"
>             + "&delay=5000&recursive=false";
>     }
>
>     @BeforeEach
>     public void setUp() throws Exception {
>         prepareFtpServer();
>     }
>
>     @Test
>     public void testFtpRoute() throws Exception {
>         resultEndpoint.expectedMessageCount(1);
>         resultEndpoint.assertIsSatisfied();
>         Exchange ex = resultEndpoint.getExchanges().get(0);
>         byte[] bytes = ex.getIn().getBody(byte[].class);
>         assertTrue(bytes.length > 10000, "Logo size wrong");
>
>         // assert the file
>         File file = testFile("deleteme.jpg").toFile();
>         assertTrue(file.exists(), "The binary file should exists");
>         assertTrue(file.length() > 10000, "Logo size wrong");
>     }
>
>     private void prepareFtpServer() throws Exception {
>         // prepares the FTP Server by creating a file on the server that
> we want
>         // to unit
>         // test that we can pool and store as a local file
>         Endpoint endpoint = context.getEndpoint(getFtpUrl());
>         Exchange exchange = endpoint.createExchange();
>         exchange.getIn().setBody(new
> File("src/test/data/ftpbinarytest/logo.jpeg"));
>         exchange.getIn().setHeader(Exchange.FILE_NAME, "logo.jpeg");
>         Producer producer = endpoint.createProducer();
>         producer.start();
>         producer.process(exchange);
>         producer.stop();
>     }
>
>     protected int getPort() {
>         System.out.println("Port:" + service.getPort());
>         return service.getPort();
>     }
>
>     protected Path ftpFile(String file) {
>         return service.getFtpRootDir().resolve(file);
>     }
>
>     protected String getFtpUrl(String user, String password) {
>         StringBuilder url = new StringBuilder("ftp://");
>         url.append(user == null ? "" : user + "@");
>         url.append("localhost:" + service.getPort() + "/");
>         url.append(password == null ? "" : "?password=" + password);
>         return url.toString();
>     }
>
>     protected void assertMockEndpointsSatisfied() throws
> InterruptedException {
>         MockEndpoint.assertIsSatisfied(this.context);
>     }
>
>     protected void sendFile(String url, Object body, String fileName) {
>         template.sendBodyAndHeader(url, body, Exchange.FILE_NAME, new
> SimpleExpression(fileName));
>     }
>
>     protected Path testFile(String dir) {
>         return this.testDirectory().resolve(dir);
>     }
>
>     protected Path testDirectory() {
>         return this.testDirectory(false);
>     }
>
>     protected Path testDirectory(boolean create) {
>         Class<?> testClass = this.getClass();
>         return testDirectory(testClass, create);
>     }
>
>     protected String fileUri(String query) {
>         Path var10000 = this.testDirectory();
>         return "file:" + var10000 + (query.startsWith("?") ? "" : "/") +
> query;
>     }
>
>     // *************************************
>     // Config
>     // *************************************
>
>     @Configuration
>     public class TestConfiguration {
>         @Bean
>         public RouteBuilder routeBuilder() {
>
>             return new RouteBuilder() {
>                 @Override
>                 public void configure() {
>                     String fileUrl =
> fileUri("?noop=true&fileExist=Override"); // <--- BREAKPOIINT
>                     from(getFtpUrl()).setHeader(Exchange.FILE_NAME,
> constant("deleteme.jpg"))
>                         .to(fileUrl,
>                             "mock:result");
>                 }
>             };
>         }
>     }
> }
>
> The trouble is - if put breakpoint in the method configure() within the
> ReouteBuilder bean, the FTP is not yet initialized and service.getPort() is
> 0
>
> How can I force FTP to be initialized before the RouteBuilder bean is
> loaded?
>
> Regards
>
> Jiři
>
>
> ________________________________
> Od: Federico Mariani <fe...@gmail.com>
> Odesláno: Úterý, 3. červen 2025 13:31
> Komu: users@camel.apache.org <us...@camel.apache.org>
> Předmět: Re: Camel Test Infrastructure FTP
>
> Hi,
>
> Did you import in your pom.xml *camel-test-infra-ftp *with type* test-jar?
> *The
> test jar contains both main and test classes
>
> https://github.com/apache/camel-spring-boot/blob/main/components-starter/camel-ftp-starter/pom.xml#L54-L60
>
> Moreover, in *camel-spring-boot* repository there are some tests that use
> *camel-test-infra-ftp*
>
> https://github.com/apache/camel-spring-boot/tree/main/components-starter/camel-ftp-starter/src/test
> .
> Maybe you can find something interesting there.
>
> Regards,
> Federico
>
> Il giorno mar 3 giu 2025 alle ore 12:24 <me...@volny.cz> ha scritto:
>
> > Hello,
> >
> > I would like to use Camel Infrastructure for my Spring Boot Camel
> > End-to-End tests.
> >
> > II have spent quite some time investigating how it works. Unfortunately
> > the documentation is very limited and I was not able to find any examples
> > either.
> >
> > I started with a very simple scenario -> one route from FTP to file.
> After
> > couple of hours I was able to come to following test that works.
> >
> > @SpringBootTest
> > @Import({ FtpServiceTestConfig.class, Process1TestRoutes.class})
> > @TestPropertySource("classpath:application-e2e.yaml")
> > @TestInstance(TestInstance.Lifecycle.PER_CLASS)
> > @ActiveProfiles("e2e")
> > public class Process1E2ETest {
> >     @Autowired
> >     CamelContext camelContext;
> >
> >     @RegisterExtension
> >     static FtpService ftpService =
> > FtpServiceFactory.createEmbeddedService();
> >
> >     @Test
> >     void shouldTransferFileFromInputToOutput() throws Exception {
> >
> >         // Create the route after FTP server is initialized
> >         camelContext.addRoutes(new RouteBuilder() {
> >             @Override
> >             public void configure() {
> >                 from("ftp://" + ftpService.hostname() + ":" +
> > ftpService.port() + "/" + ftpService.directoryName()
> >                     + "?username=" + ftpService.username()
> >                     + "&password=" + ftpService.password()
> >                     + "&delete=true&delay=1000")
> >                     .to("file:target/out")
> >                     .log("Received: ${file:name}");
> >             }
> >         });
> >
> >         // Ensure target directory exists
> >         Files.createDirectories(Path.of("target/out"));
> >
> >         // Create input file in the correct FTP directory
> >         Path ftpRootDir = ftpService.getFtpRootDir();
> >         Path ftpInputDir =
> ftpRootDir.resolve(ftpService.directoryName());
> >         Files.createDirectories(ftpInputDir);
> >         Path inputFile = ftpInputDir.resolve("test.txt");
> >         Files.writeString(inputFile, "Hello from test",
> > StandardOpenOption.CREATE);
> >
> >         System.out.println("Created file at: " +
> > inputFile.toAbsolutePath());
> >
> >         // Wait longer for Camel route to process the file
> >         Thread.sleep(5000);
> >
> >         Path outputFile = Path.of("target/out/test.txt");
> >         assertTrue(Files.exists(outputFile), "Output file should exist at
> > " + outputFile.toAbsolutePath());
> >         String content = Files.readString(outputFile);
> >         assertEquals("Hello from test", content);
> >     }
> > }
> >
> > I had to copy FtpService  and FtpServiceFactory with their dependencies
> > from Camel Github Repository (
> >
> https://github.com/apache/camel/tree/camel-4.12.x/test-infra/camel-test-infra-ftp/src/test/java/org/apache/camel/test/infra/ftp/services
> )
> > as they are not included in maven dependency jar. I am using Apache Camel
> > 4.12.0
> >
> > I do not like the solution much as it creates the route only inside the
> > test that is kind of ugly. If I try to create it in @TestConfiguration or
> > even @BeforeAll the troube is that the FTP server is not initalized yet
> and
> > ftpService.port() is 0 at that time.
> >
> > Can anyone explain me how it is meant to be used and/or provide some
> > example?
> >
> > Regards
> >
> > Jiří
> >
>

Re: Camel Test Infrastructure FTP

Posted by "medved@volny.cz" <me...@volny.cz>.
Hi,

thank you very much for your feedback. Type test-jar helped to include the test classes. I tried to replicate some test fro camel-spring-boot but I think I miss some important part to the puzzle. This is my test class derived from https://github.com/apache/camel-spring-boot/blob/main/components-starter/camel-ftp-starter/src/test/java/org/apache/camel/component/file/remote/springboot/ftp/FromFtpToBinaryFileTest.java

I have just included the parent classes to make it compact.


@DirtiesContext
@CamelSpringBootTest
@SpringBootTest(classes = {CamelAutoConfiguration.class, Process1E2ETest.class,
    Process1E2ETest.TestConfiguration.class})
// Baaed on FromFtpToBinaryFileIT
public class Process1E2ETest {

    @RegisterExtension
    static FtpEmbeddedService service = new FtpEmbeddedService();

    @Autowired
    protected CamelContext context;

    @Autowired
    protected ProducerTemplate template;

    @EndpointInject("mock:result")
    private MockEndpoint resultEndpoint;

    protected static void assertFileExists(String filename) {
        File file = new File(filename);
        assertTrue(file.exists(), "File " + filename + " should exist");
        assertTrue(file.isFile(), "File " + filename + " should be a file");
    }

    protected static void assertFileNotExists(Path file) {
        Assertions.assertFalse(
            Files.exists(file, new LinkOption[0]), "File " + file + " should not exist");
    }

    protected static void assertFileExists(Path file, String content) throws IOException {
        assertTrue(Files.exists(file, new LinkOption[0]), "File " + file + " should exist");
        assertTrue(Files.isRegularFile(file, new LinkOption[0]),
            "File " + file + " should be a file");
        Assertions.assertEquals(content, new String(Files.readAllBytes(file)),
            "File " + file + " has unexpected content");
    }

    public static Path testDirectory(Class<?> testClass, boolean create) {
        Path dir = Paths.get("target", "data", testClass.getSimpleName());
        if (create) {
            try {
                Files.createDirectories(dir);
            } catch (IOException var4) {
                throw new IllegalStateException("Unable to create test directory: " + dir, var4);
            }
        }

        return dir;
    }

    // must user "consumer." prefix on the parameters to the file component
    private String getFtpUrl() {
        return "ftp://admin@localhost:" + getPort() + "/tmp4/camel?password=admin&binary=true"
            + "&delay=5000&recursive=false";
    }

    @BeforeEach
    public void setUp() throws Exception {
        prepareFtpServer();
    }

    @Test
    public void testFtpRoute() throws Exception {
        resultEndpoint.expectedMessageCount(1);
        resultEndpoint.assertIsSatisfied();
        Exchange ex = resultEndpoint.getExchanges().get(0);
        byte[] bytes = ex.getIn().getBody(byte[].class);
        assertTrue(bytes.length > 10000, "Logo size wrong");

        // assert the file
        File file = testFile("deleteme.jpg").toFile();
        assertTrue(file.exists(), "The binary file should exists");
        assertTrue(file.length() > 10000, "Logo size wrong");
    }

    private void prepareFtpServer() throws Exception {
        // prepares the FTP Server by creating a file on the server that we want
        // to unit
        // test that we can pool and store as a local file
        Endpoint endpoint = context.getEndpoint(getFtpUrl());
        Exchange exchange = endpoint.createExchange();
        exchange.getIn().setBody(new File("src/test/data/ftpbinarytest/logo.jpeg"));
        exchange.getIn().setHeader(Exchange.FILE_NAME, "logo.jpeg");
        Producer producer = endpoint.createProducer();
        producer.start();
        producer.process(exchange);
        producer.stop();
    }

    protected int getPort() {
        System.out.println("Port:" + service.getPort());
        return service.getPort();
    }

    protected Path ftpFile(String file) {
        return service.getFtpRootDir().resolve(file);
    }

    protected String getFtpUrl(String user, String password) {
        StringBuilder url = new StringBuilder("ftp://");
        url.append(user == null ? "" : user + "@");
        url.append("localhost:" + service.getPort() + "/");
        url.append(password == null ? "" : "?password=" + password);
        return url.toString();
    }

    protected void assertMockEndpointsSatisfied() throws InterruptedException {
        MockEndpoint.assertIsSatisfied(this.context);
    }

    protected void sendFile(String url, Object body, String fileName) {
        template.sendBodyAndHeader(url, body, Exchange.FILE_NAME, new SimpleExpression(fileName));
    }

    protected Path testFile(String dir) {
        return this.testDirectory().resolve(dir);
    }

    protected Path testDirectory() {
        return this.testDirectory(false);
    }

    protected Path testDirectory(boolean create) {
        Class<?> testClass = this.getClass();
        return testDirectory(testClass, create);
    }

    protected String fileUri(String query) {
        Path var10000 = this.testDirectory();
        return "file:" + var10000 + (query.startsWith("?") ? "" : "/") + query;
    }

    // *************************************
    // Config
    // *************************************

    @Configuration
    public class TestConfiguration {
        @Bean
        public RouteBuilder routeBuilder() {

            return new RouteBuilder() {
                @Override
                public void configure() {
                    String fileUrl = fileUri("?noop=true&fileExist=Override"); // <--- BREAKPOIINT
                    from(getFtpUrl()).setHeader(Exchange.FILE_NAME, constant("deleteme.jpg"))
                        .to(fileUrl,
                            "mock:result");
                }
            };
        }
    }
}

The trouble is - if put breakpoint in the method configure() within the ReouteBuilder bean, the FTP is not yet initialized and service.getPort() is 0

How can I force FTP to be initialized before the RouteBuilder bean is loaded?

Regards

Jiři


________________________________
Od: Federico Mariani <fe...@gmail.com>
Odesláno: Úterý, 3. červen 2025 13:31
Komu: users@camel.apache.org <us...@camel.apache.org>
Předmět: Re: Camel Test Infrastructure FTP

Hi,

Did you import in your pom.xml *camel-test-infra-ftp *with type* test-jar? *The
test jar contains both main and test classes
https://github.com/apache/camel-spring-boot/blob/main/components-starter/camel-ftp-starter/pom.xml#L54-L60

Moreover, in *camel-spring-boot* repository there are some tests that use
*camel-test-infra-ftp*
https://github.com/apache/camel-spring-boot/tree/main/components-starter/camel-ftp-starter/src/test.
Maybe you can find something interesting there.

Regards,
Federico

Il giorno mar 3 giu 2025 alle ore 12:24 <me...@volny.cz> ha scritto:

> Hello,
>
> I would like to use Camel Infrastructure for my Spring Boot Camel
> End-to-End tests.
>
> II have spent quite some time investigating how it works. Unfortunately
> the documentation is very limited and I was not able to find any examples
> either.
>
> I started with a very simple scenario -> one route from FTP to file. After
> couple of hours I was able to come to following test that works.
>
> @SpringBootTest
> @Import({ FtpServiceTestConfig.class, Process1TestRoutes.class})
> @TestPropertySource("classpath:application-e2e.yaml")
> @TestInstance(TestInstance.Lifecycle.PER_CLASS)
> @ActiveProfiles("e2e")
> public class Process1E2ETest {
>     @Autowired
>     CamelContext camelContext;
>
>     @RegisterExtension
>     static FtpService ftpService =
> FtpServiceFactory.createEmbeddedService();
>
>     @Test
>     void shouldTransferFileFromInputToOutput() throws Exception {
>
>         // Create the route after FTP server is initialized
>         camelContext.addRoutes(new RouteBuilder() {
>             @Override
>             public void configure() {
>                 from("ftp://" + ftpService.hostname() + ":" +
> ftpService.port() + "/" + ftpService.directoryName()
>                     + "?username=" + ftpService.username()
>                     + "&password=" + ftpService.password()
>                     + "&delete=true&delay=1000")
>                     .to("file:target/out")
>                     .log("Received: ${file:name}");
>             }
>         });
>
>         // Ensure target directory exists
>         Files.createDirectories(Path.of("target/out"));
>
>         // Create input file in the correct FTP directory
>         Path ftpRootDir = ftpService.getFtpRootDir();
>         Path ftpInputDir = ftpRootDir.resolve(ftpService.directoryName());
>         Files.createDirectories(ftpInputDir);
>         Path inputFile = ftpInputDir.resolve("test.txt");
>         Files.writeString(inputFile, "Hello from test",
> StandardOpenOption.CREATE);
>
>         System.out.println("Created file at: " +
> inputFile.toAbsolutePath());
>
>         // Wait longer for Camel route to process the file
>         Thread.sleep(5000);
>
>         Path outputFile = Path.of("target/out/test.txt");
>         assertTrue(Files.exists(outputFile), "Output file should exist at
> " + outputFile.toAbsolutePath());
>         String content = Files.readString(outputFile);
>         assertEquals("Hello from test", content);
>     }
> }
>
> I had to copy FtpService  and FtpServiceFactory with their dependencies
> from Camel Github Repository (
> https://github.com/apache/camel/tree/camel-4.12.x/test-infra/camel-test-infra-ftp/src/test/java/org/apache/camel/test/infra/ftp/services)
> as they are not included in maven dependency jar. I am using Apache Camel
> 4.12.0
>
> I do not like the solution much as it creates the route only inside the
> test that is kind of ugly. If I try to create it in @TestConfiguration or
> even @BeforeAll the troube is that the FTP server is not initalized yet and
> ftpService.port() is 0 at that time.
>
> Can anyone explain me how it is meant to be used and/or provide some
> example?
>
> Regards
>
> Jiří
>

Re: Camel Test Infrastructure FTP

Posted by Federico Mariani <fe...@gmail.com>.
Hi,

Did you import in your pom.xml *camel-test-infra-ftp *with type* test-jar? *The
test jar contains both main and test classes
https://github.com/apache/camel-spring-boot/blob/main/components-starter/camel-ftp-starter/pom.xml#L54-L60

Moreover, in *camel-spring-boot* repository there are some tests that use
*camel-test-infra-ftp*
https://github.com/apache/camel-spring-boot/tree/main/components-starter/camel-ftp-starter/src/test.
Maybe you can find something interesting there.

Regards,
Federico

Il giorno mar 3 giu 2025 alle ore 12:24 <me...@volny.cz> ha scritto:

> Hello,
>
> I would like to use Camel Infrastructure for my Spring Boot Camel
> End-to-End tests.
>
> II have spent quite some time investigating how it works. Unfortunately
> the documentation is very limited and I was not able to find any examples
> either.
>
> I started with a very simple scenario -> one route from FTP to file. After
> couple of hours I was able to come to following test that works.
>
> @SpringBootTest
> @Import({ FtpServiceTestConfig.class, Process1TestRoutes.class})
> @TestPropertySource("classpath:application-e2e.yaml")
> @TestInstance(TestInstance.Lifecycle.PER_CLASS)
> @ActiveProfiles("e2e")
> public class Process1E2ETest {
>     @Autowired
>     CamelContext camelContext;
>
>     @RegisterExtension
>     static FtpService ftpService =
> FtpServiceFactory.createEmbeddedService();
>
>     @Test
>     void shouldTransferFileFromInputToOutput() throws Exception {
>
>         // Create the route after FTP server is initialized
>         camelContext.addRoutes(new RouteBuilder() {
>             @Override
>             public void configure() {
>                 from("ftp://" + ftpService.hostname() + ":" +
> ftpService.port() + "/" + ftpService.directoryName()
>                     + "?username=" + ftpService.username()
>                     + "&password=" + ftpService.password()
>                     + "&delete=true&delay=1000")
>                     .to("file:target/out")
>                     .log("Received: ${file:name}");
>             }
>         });
>
>         // Ensure target directory exists
>         Files.createDirectories(Path.of("target/out"));
>
>         // Create input file in the correct FTP directory
>         Path ftpRootDir = ftpService.getFtpRootDir();
>         Path ftpInputDir = ftpRootDir.resolve(ftpService.directoryName());
>         Files.createDirectories(ftpInputDir);
>         Path inputFile = ftpInputDir.resolve("test.txt");
>         Files.writeString(inputFile, "Hello from test",
> StandardOpenOption.CREATE);
>
>         System.out.println("Created file at: " +
> inputFile.toAbsolutePath());
>
>         // Wait longer for Camel route to process the file
>         Thread.sleep(5000);
>
>         Path outputFile = Path.of("target/out/test.txt");
>         assertTrue(Files.exists(outputFile), "Output file should exist at
> " + outputFile.toAbsolutePath());
>         String content = Files.readString(outputFile);
>         assertEquals("Hello from test", content);
>     }
> }
>
> I had to copy FtpService  and FtpServiceFactory with their dependencies
> from Camel Github Repository (
> https://github.com/apache/camel/tree/camel-4.12.x/test-infra/camel-test-infra-ftp/src/test/java/org/apache/camel/test/infra/ftp/services)
> as they are not included in maven dependency jar. I am using Apache Camel
> 4.12.0
>
> I do not like the solution much as it creates the route only inside the
> test that is kind of ugly. If I try to create it in @TestConfiguration or
> even @BeforeAll the troube is that the FTP server is not initalized yet and
> ftpService.port() is 0 at that time.
>
> Can anyone explain me how it is meant to be used and/or provide some
> example?
>
> Regards
>
> Jiří
>