I would like to right unit and integration test cases to test all the functional flow. Can someone share your thoughts on how I can create a mock endpoint to watch directory for file creation and further process them via multiple routes and move the file to different directories.
- Monitoring the
/hellodirectory for new file creation. - If there is a file based on the file prefix, updated the headers with container name.
- Upload to appropriate azure blob container based on file name.
- Make an api call and move the file to
/successdirectory once its processed.
FileWatcherRoute.java
@Service
public class FileWatcherRoute extends RouteBuilder {
@Value("${watcher-base-url}")
private String baseUrl;
@Value("${watcher-subscription-key}")
private String subscriptionKey;
@Override
public void configure() {
Processor logResponse = exchange -> log
.info("The response code is: {}", exchange.getIn().getHeader(Exchange.HTTP_RESPONSE_CODE));
from("file-watch:hello?events=CREATE&antInclude=**/*.csv&recursive=true")
.routeId("fileWatch")
.to("direct:updateHeaders")
.end();
from("direct:updateHeaders")
.routeId("updateHeaders")
.choice()
.when((exchange -> exchange.getIn().getHeader(Exchange.FILE_NAME).toString().trim().matches("\\d{8}_\\d{4}(_Inventory.csv)")))
.setHeader("CamelAzureStorageBlobContainerName", constant(AppConstants.STORE))
.when(exchange -> exchange.getIn().getHeader(Exchange.FILE_NAME).toString().trim().matches("\\d{8}-\\d{6}_Idle_Inventory_\\d{4}.csv"))
.setHeader("CamelAzureStorageBlobContainerName",constant(AppConstants.IDLE_FILE))
.toD("direct:uploadFileToBlob")
.end();
from("direct:uploadFileToBlob")
.routeId("uploadFile")
.log("Container Name: ${header.CamelAzureStorageBlobContainerName}")
.toD("azure-storage-blob://{accName}/${header.CamelAzureStorageBlobContainerName}?blobName=${header.CamelFileName}&operation=uploadBlockBlob&serviceClient=#serviceClient")
.to("direct:startRestApi")
.log("${header.CamelFileName} Uploaded to ${header.CamelAzureStorageBlobContainerName} Container Successfully")
.end();
from("direct:startRestApi")
.routeId("restCall")
.setHeader(Exchange.HTTP_METHOD, constant("GET"))
.setHeader("Content-Type",constant("application/json"))
.setHeader("Ocp-Apim-Subscription-Key",constant(subscriptionKey))
.to(baseUrl)
.to("direct:processedFiles")
.process(logResponse)
.end();
from("direct:processedFiles")
.routeId("fileProcessing")
.choice()
.when(exchange -> exchange.getIn().getHeader(Exchange.HTTP_RESPONSE_CODE).equals(200))
.to("file://success")
.otherwise()
.to("file://error")
.end();
}
}
FileWatcherRouteTest.java
@CamelSpringBootTest
@SpringBootTest
@MockEndpoints
@UseAdviceWith
public class FileWatcherRouteTest {
@Autowired
CamelContext camelContext;
@Autowired
ProducerTemplate producerTemplate;
@EndpointInject("mock:processedFiles")
MockEndpoint mockEndpoint;
@Test
void when_new_file_created_should_update_header_with_container_name_and_upload_to_container() throws Exception {
AdviceWith.adviceWith(camelContext, "fileWatch", routeBuilder -> {
routeBuilder.replaceFromWith("direct:file-watch");
});
camelContext.start();
mockEndpoint.assertIsSatisfied();
}
}
MockEndpoint only supports producer endpoints. This is due to the fact that it is designed to perform assertions to Exchanges and Messages.
For example:
When testing a route you should use ProducerTemplate send methods to start the route under test with whatever body, headers and properties you want to test with it.
In your case you can use java file operations to read a file from test resources folder as string, byte array or stream and use send it as body along with headers
CamelFileNameandCamelFileEventTypeto target route.I would also recommend treating your direct routes like functions to make them easier to test. Meaning that instead of jumping from route to route you could have parent route that just calls the child routes in correct order.
This allows you easily write individual tests for
direct:updateHeaders,direct:uploadFileToBlobanddirect:processedFilesFor example:
direct:uploadFileToBlobthrows proper exception if one of the required headers is missing or somehow invalid.direct:uploadFileToBlobproperly handles connection exceptions with azure.direct:processedFilesplaces files to correct folders.If you want to test file output you can use JUnits
TemporaryFolderto create temporary folder which you can then target with your file producer endpoint. After route has completed you can use basicassertEqualsand file operations to check whether the output meets your test requirements.Apache Commons IO is also pretty handy library for tests for reading files from resources and copying files to TemporaryFolder.
Couple examples with files, ProducerTemplate, Commons IO and CamelTestSupport:
Above examples using Camel 3.4.4