Issue
I am trying to test a route which is like this:
from("s3://bucketName")
.process(exchange -> {exchange.getIn().setHeader(Exchange.FILE_NAME,MY_FILE_NAME);})
.log("File download Successful")
.to("file:" + FILE_PATH).routeId("mys3Route");
I have written my test like this:
@Test
public void testFileMovement() throws Exception {
AdviceWith.adviceWith(context, "mys3Route", a -> {
a.replaceFromWith("mock:s3Location");
a.interceptSendToEndpoint("file:" + FILE_PATH).skipSendToOriginalEndpoint()
.to("mock:anotherLocation");
});
MockEndpoint mockedToEndPoint = getMockEndpoint("mock:anotherLocation");
mockedToEndPoint.setExpectedMessageCount(1);
template.sendBody("mock:s3Location", "Just Text");
mockedToEndPoint.assertIsSatisfied();
Thread.sleep(5000);
}
Whenever I run this as unit test case, I get this error:
org.apache.camel.CamelExecutionException: Exception occurred during >execution on the exchange: Exchange[]
The error seems to be coming up here in: org.apache.camel.impl.engine.DefaultProducerTemplate.extractResultBody(DefaultProducerTemplate.java:591)
(which is present in camel dependencies).
Any idea as to what I am doing wrong and how I can rectify it? Any help to resolve and understand this issue is greatly appreciated .
Solution
For starters you probably should not replace consumer/From endpoint with MockEndpoint just use direct endpoint. MockEndpoints only support producer endpoints (to) and should not be used as consumer endpoint (from). MockEndpoints are meant to be used as points on your route where you want to do assertions on things like message body, exchange properties, received messages etc.
Secondly if you're using AdviceWith you should set the isUseAdviceWith to true and start the context manually just before you use template.send
methods. How this is set varies a bit if you're using spring boot annotations or not. Example below uses just simple CamelTestSupport.
Thirdly you rarely if ever need to use intercept on camel tests, use weaveById, weaveByToURI with replace instead. In this case you're better off just fixing how your file-path and file-name is set by using property-placeholders instead. This way you can just use useOverridePropertiesWithPropertiesComponent and TemporaryFolder feature of junit. Also Apache-commons IO FileUtils is pretty handy if you need to read file-contents of a test file or copy something to a test folder.
Using Thread.Sleep with unit tests is hacky at best and should be avoided. For this case I see no reason why you would use it. RouteId is best placed at the top of the route.
Example:
package com.example;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Properties;
import org.apache.camel.RoutesBuilder;
import org.apache.camel.builder.AdviceWithRouteBuilder;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.mock.MockEndpoint;
import org.apache.camel.test.junit4.CamelTestSupport;
import org.apache.commons.io.FileUtils;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
public class ExampleTest extends CamelTestSupport {
@Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();
File outputFolder;
static final String FILE_NAME = "testfile.txt";
@Test
public void testFileMovement() throws Exception {
context.getRouteDefinition("mys3Route")
.adviceWith(context, new AdviceWithRouteBuilder(){
@Override
public void configure() throws Exception {
replaceFromWith("direct:start");
weaveAddLast()
.to("mock:result");
}
});
MockEndpoint resultMockEndpoint = getMockEndpoint("mock:result");
resultMockEndpoint.setExpectedMessageCount(1);
startCamelContext();
template.sendBody("direct:start", "Just Text");
File file = new File(outputFolder, FILE_NAME);
assertEquals(true, file.exists());
String fileContents = FileUtils.readFileToString(file, StandardCharsets.UTF_8);
assertEquals("Just Text", fileContents);
resultMockEndpoint.assertIsSatisfied();
}
@Override
protected RoutesBuilder createRouteBuilder() throws Exception {
return new RouteBuilder(){
@Override
public void configure() throws Exception {
from("s3://bucketName")
.routeId("mys3Route")
.log("File download Successful")
.to("file:{{filepath}}?fileName={{filename}}");
}
};
}
@Override
protected Properties useOverridePropertiesWithPropertiesComponent() {
try {
outputFolder = temporaryFolder.newFolder("output");
} catch (IOException e) {
e.printStackTrace();
}
Properties properties = new Properties();
properties.put("filename", FILE_NAME);
properties.put("filepath", outputFolder.getPath());
return properties;
}
@Override
public boolean isUseAdviceWith() {
return true;
}
}
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons-io.version}</version>
</dependency>
Answered By - Pasi Österman
Answer Checked By - Marie Seifert (JavaFixing Admin)