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 [email protected] <[email protected]>
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 <[email protected]>
> Odesláno: Úterý, 3. červen 2025 13:31
> Komu: [email protected] <[email protected]>
> 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 <[email protected]> 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ří
> >
>