测试Camel sFTP端点:关于指定路由及unzipLibFile的技术咨询
unzipLibFile Logic Guide Let's break this down into two clear parts: validating your route's behavior, and nailing the unzip bean's implementation.
1. Route Testing Strategy
Camel has excellent tooling for testing routes without needing a real SFTP server. We'll cover both unit tests (focused on logic branches) and integration tests (end-to-end with a simulated SFTP server).
Unit Testing (Mock Dependencies)
Use CamelTestSupport along with Mockito to mock your helper beans (isFilenameAlreadyImported, unzipLibFile, persistFilename) and validate route branching.
Here's a concrete test example:
public class LibFtpRouteTest extends CamelTestSupport { @MockBean private IsFilenameAlreadyImported isFilenameAlreadyImported; @MockBean private UnzipLibFile unzipLibFile; @MockBean private PersistFilename persistFilename; @Override protected RoutesBuilder createRouteBuilder() { return new YourRouteConfigurationClass(); // Replace with your actual route class } // Test the "file already imported" branch @Test public void testExistingFileRoute() throws Exception { // Mock the filename check to return true when(isFilenameAlreadyImported.check(any(Exchange.class))).thenReturn(true); // Send a test file to the route (use direct endpoint for testing instead of SFTP) template.sendBodyAndHeader("direct:import-lib-files", "dummy zip content", Exchange.FILE_NAME, "existing-file.zip"); // Verify unzip and persist beans are NOT triggered verify(unzipLibFile, never()).unzip(any(Exchange.class)); verify(persistFilename, never()).persist(any(Exchange.class)); // Validate log output (optional but useful) MockEndpoint logMock = getMockEndpoint("log:*"); logMock.expectedMessagesMatches( body().contains("Processing file: 'existing-file.zip'"), body().contains("'existing-file.zip' is already imported.") ); logMock.assertIsSatisfied(); } // Test the "new file import" branch @Test public void testNewFileRoute() throws Exception { when(isFilenameAlreadyImported.check(any(Exchange.class))).thenReturn(false); template.sendBodyAndHeader("direct:import-lib-files", "dummy zip content", Exchange.FILE_NAME, "new-file.zip"); // Verify unzip and persist are called once verify(unzipLibFile, times(1)).unzip(any(Exchange.class)); verify(persistFilename, times(1)).persist(any(Exchange.class)); // Validate success logs MockEndpoint logMock = getMockEndpoint("log:*"); logMock.expectedMessagesMatches( body().contains("Processing file: 'new-file.zip'"), body().contains("Import file 'new-file.zip'.") ); logMock.assertIsSatisfied(); } }
Integration Testing (Simulated SFTP Server)
For end-to-end validation, use an embedded SFTP server like Apache Mina SSHD to mimic a real environment:
- Add Mina SSHD dependencies to your test scope
- In test setup, start the embedded server, create a test zip file in its directory
- Configure your Camel FTP endpoint to point to the embedded server (use localhost, test port, and credentials)
- Run the route and verify:
- The file is pulled from the SFTP server
- Unzipping works as expected
- The filename is persisted correctly
2. unzipLibFile Bean Technical Considerations
When implementing the unzip logic, keep these critical points in mind:
Access the Input File Correctly
The SFTP endpoint passes a GenericFile<InputStream> in the exchange body. Retrieve it like this:
GenericFile<InputStream> sftpFile = exchange.getIn().getBody(GenericFile.class); InputStream zipStream = sftpFile.getInputStream();
Robust Unzipping Logic
Use Java's built-in ZipInputStream or Apache Commons Compress for better error handling. Process every entry in the zip (don't skip directories or multiple files):
public void unzip(Exchange exchange) throws IOException { GenericFile<InputStream> sftpFile = exchange.getIn().getBody(GenericFile.class); List<File> extractedFiles = new ArrayList<>(); try (ZipInputStream zis = new ZipInputStream(sftpFile.getInputStream())) { ZipEntry entry; while ((entry = zis.getNextEntry()) != null) { if (!entry.isDirectory()) { // Create a temporary file to store extracted content File tempFile = File.createTempFile("lib-extracted-", entry.getName()); try (FileOutputStream fos = new FileOutputStream(tempFile)) { IOUtils.copy(zis, fos); // Use Apache Commons IO for safe stream copying } extractedFiles.add(tempFile); } zis.closeEntry(); } } // Pass extracted files to downstream processors (if needed) exchange.getIn().setBody(extractedFiles); // Preserve original filename for the persist step exchange.getIn().setHeader(Exchange.FILE_NAME, sftpFile.getFileName()); }
Error Handling & Cleanup
- Handle Corrupted Zips: Wrap unzip logic in try-catch blocks for
ZipExceptionorIOException, throw a custom exception that your Camel route can handle withonException(e.g., log the error, move the bad file to a dead-letter directory). - Cleanup Temp Files: Add a step to delete temporary extracted files after processing. You can use Camel's
fileDeleteoption or a dedicated cleanup bean in afinallyblock.
Preserve Camel Context
Don't forget to keep important headers (like CamelFileName) intact so the persistFilename bean knows which original file was processed. If you need to pass extracted file metadata downstream, store it in exchange headers or the body.
内容的提问来源于stack exchange,提问作者SleepyX667

