...
Code Block | ||
---|---|---|
| ||
@RunWith(PaxExam.class)
@ExamReactorStrategy(PerClass.class)
public class PaxCdiOsgiTest {
@Configuration
public Option[] config() throws IOException {
return options(
// Karaf configuration
karafDistributionConfiguration()
.frameworkUrl(
maven()
.groupId("org.apache.karaf")
.artifactId("apache-karaf")
.versionAsInProject()
.type("zip"))
.name("Apache Karaf")
.unpackDirectory(new File("target/paxexam/unpack/")),
// PAX CDI Weld
features(
maven()
.groupId("org.ops4j.pax.cdi")
.artifactId("pax-cdi-features")
.type("xml")
.classifier("features")
.versionAsInProject(),
"pax-cdi-weld"),
// Karaf Camel commands
mavenBundle()
.groupId("your.application.groupId")
.artifactId("your.application.artifactId")
.versionAsInProject()
);
}
@Inject
private CamelContext context;
@Test
public void testContextStatus() {
assertThat("Camel context status is incorrect!",
context.getStatus(), equalTo(ServiceStatus.Started));
}
}
|
You can see the tests in the camel-example-cdi-osgi
example for a complete working example of testing a Camel CDI application deployed in an OSGi container using PAX Exam.
...
You can see the tests in the camel-example-cdi-test
example for a thorough overview of the following testing patterns for Camel CDI applications.
Routes advising with adviceWith
AdviceWith
is used for testing Camel routes where you can advice an existing route before its being tested. It allows to add Intercept or weave routes for testing purpose, for example using the Mock component.
Test routes
You may want to add some Camel routes to your Camel CDI applications for testing purpose. For example to route some exchanges to a MockEndpoint
instance. You can do that by declaring a RouteBuilder
bean within the test class as you would normally do in your application codeIt is recommended to only advice routes which are not started already. To meet that requirement, you can use the CamelContextStartingEvent
event by declaring an observer method in which you use adviceWith
to add a mock
endpoint at the end of your Camel route, e.g.:
Code Block | ||
---|---|---|
| ||
void advice(@Observes CamelContextStartingEvent event,@RunWith(CamelCdiRunner.class) public class CamelCdiTest { // Declare a RouteBuilder bean for testing @Uri("mock:test") MockEndpoint messages, purpose // that is automatically added to the Camel context static ModelCamelContextclass context)TestRoute throwsextends ExceptionRouteBuilder { context.getRouteDefinition("route")@Override public void .adviceWith(context, new AdviceWithRouteBuilder(configure() { @Overridefrom("direct:out").routeId("test").to("mock:out"); } // And retrieve the publicMockEndpoint voidfor configure()further {assertions @Inject weaveAddLast().to(@Uri("mock:testout"); } }); } |
Bean alternatives
Test routes
Camel context customisation
MockEndpoint mock;
} |
You can find more information in auto-detecting Camel routes.
Bean alternatives
You may want to replace a bean that is used in your Camel routes by another bean You may need to customise your Camel contexts for testing purpose, for example to mock it or change the behaviour of the application bean.
Imagine you have the following route in your application:
Code Block | ||
---|---|---|
| ||
public class Application {
@ContextName("camel-test-cdi")
static class Hello extends RouteBuilder {
@Override
public void configure() {
from("direct:in").bean("bean").to("direct:out");
}
} |
And the corresponding bean:
Code Block | ||
---|---|---|
| ||
@Named("bean")
public class Bean {
public String process(@Body String body) {
return body;
}
} |
Then you can replace the bean above in your tests by declaring an alternative bean, annotated with @Alternative
, e.g.:
Code Block | ||
---|---|---|
| ||
@Alternative
@Named("bean")
public class AlternativeBean {
public String process(@Body String body) {
return body + " with alternative bean!";
}
} |
And you need to activate (a.k.a. select in CDI terminology) this alternative bean in your tests. If your using the CamelCdiRunner
JUnit runner, you can do that with the @Beans
annotation provided by the Camel CDI test module, e.g.:
Code Block | ||
---|---|---|
| ||
@RunWith(CamelCdiRunner.class)
@Beans(alternatives = AlternativeBean.class)
public class CamelCdiTest {
@Test
public void testAlternativeBean(@Uri("direct:in") ProducerTemplate producer
@Uri("mock:out") MockEndpoint mock) throws InterruptedException {
mock.expectedMessageCount(1);
mock.expectedBodiesReceived("test with alternative bean!");
producer.sendBody("test");
MockEndpoint.assertIsSatisfied(1L, TimeUnit.SECONDS, mock);
}
static class TestRoute extends RouteBuilder {
@Override
public void configure() {
from("direct:out").routeId("test").to("mock:out");
}
}
} |
Camel context customisation
You may need to customise your Camel contexts for testing purpose, for example disabling JMX management to avoid TCP port allocation conflict. You can do that by declaring a custom Camel context bean in your test class, e.g.:
Code Block | ||
---|---|---|
| ||
@RunWith(CamelCdiRunner.class)
public class CamelCdiTest {
@Default
@ContextName("camel-test-cdi")
@ApplicationScoped
static class CustomCamelContext extends DefaultCamelContext {
@PostConstruct
void customize() {
disableJMX();
}
}
} |
In that example, the custom Camel context bean declared in the test class will be used during the test execution instead of the default Camel context bean provided by the Camel CDI component.
Routes advising with adviceWith
AdviceWith
is used for testing Camel routes where you can advice an existing route before its being tested. It allows to add Intercept or weave routes for testing purpose, for example using the Mock component.
It is recommended to only advice routes which are not started already. To meet that requirement, you can use the CamelContextStartingEvent
event by declaring an observer method in which you use adviceWith
to add a mock
endpoint at the end of your Camel route disabling JMX management to avoid TCP port allocation conflict. You can do that by declaring a custom Camel context bean in your test class, e.g.:
Code Block | ||
---|---|---|
| ||
@RunWith(CamelCdiRunner.class) public class CamelCdiTest { @Defaultvoid advice(@Observes CamelContextStartingEvent event, @Uri("mock:test") MockEndpoint messages, ModelCamelContext context) throws Exception { @ContextNamecontext.getRouteDefinition("camel-test-cdiroute") @ApplicationScoped.adviceWith(context, new AdviceWithRouteBuilder() { static class CustomCamelContext extends DefaultCamelContext { @Override @PostConstruct public void customizeconfigure() { disableJMX( weaveAddLast().to("mock:test"); } }); } |
In that example, the custom Camel context bean declared in the test class will be used during the test execution instead of the default Camel context bean provided by the Camel CDI component.
JUnit rules
Camel CDI test starts the CDI container after all the JUnit class rules have executed.
That way, you can use JUnit class rules to initialise (resp. clean-up) resources that your test classes would require during their execution before the container initialises (resp. after the container has shutdown). For example, you could use an embedded JMS broker like like ActiveMQ Artemis to to test your Camel JMS application, e.g.:
Code Block | ||
---|---|---|
| ||
import org.apache.activemq.artemis.jms.server.embedded.EmbeddedJMS; @RunWith(CamelCdiRunner.class) public class CamelCdiTest { @ClassRule public static final ExternalResource resources = new ExternalResource() { private final EmbeddedJMS jms = new EmbeddedJMS(); @Override protected void before() throws Exception { jms.start(); } @Override protected void after() throws Exception { jms.stop(); } }; @Inject @Uri("jms:destination") private ProducerTemplate producer; @Test public void sendMessage() { producer.sendBody("message"); } } |
Another use case is to assert the behaviour of your application after it has shutdown. In that case, you can use the the Verifier
rule rule, e.g.:
Code Block | ||
---|---|---|
| ||
import org.junit.rules.Verifier; @RunWith(CamelCdiRunner.class) public class CamelCdiTest { @ClassRule public static Verifier verifier = new Verifier() { @Override protected void verify() { // Executes after the CDI container has shutdown } }; } |
...