Testing is a crucial part of any development or integration work. In case you're using the Camel CDI integration for your applications, you have a number of options to ease testing.
You can use CDI for IoC and the Camel testing endpoints like DataSet
, Mock
, Test
and testing API like AdviceWith
and NotifyBuilder
to create sophisticated integration/unit tests that are easy to run and debug inside your IDE.
There are two supported approaches for testing with CDI in Camel:
Name | Testing Frameworks Supported | Description |
---|---|---|
Camel CDI Test |
| Available as of Camel 2.17 The Camel CDI test module ( |
Arquillian |
| Arquillian is a testing platform that handles all the plumbing of in-container testing with support for a wide range of target containers. Arquillian can be configured to run your test classes in embedded (in JVM CDI), managed (a real Web server or Java EE application server instance started in a separate process) or remote (the lifecycle of the container isn't managed by Arquillian) modes. You have to create the System Under Test (SUT) in your test classes using ShrinkWrap Descriptors. The benefit is that you have a very fine-grained control over the application configuration that you want to test. The downside is more code and more complex classpath / class loading structure. |
PAX Exam |
| PAX Exam lets you test your Camel applications in OSGi, Java EE or standalone CDI containers with the ability to finely configured your System Under Test (SUT), Similarly to Arquillian. You can use it to test your Camel CDI applications that target OSGi environments like Karaf with PAX CDI, but you can use it as well to test your Camel CDI applications in standalone CDI containers, Web containers and Java EE containers. |
Camel CDI Test
With this approach, your test classes use the JUnit runner provided in Camel CDI test. This runner manages the lifecycle of a standalone CDI container and automatically assemble and deploy the System Under Test (SUT) based on the classpath into the container.
It deploys the test class as a CDI bean so that dependency injection and any CDI features is available within the test class.
Maven users will need to add the following dependency to their pom.xml
for this component:
<dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-test-cdi</artifactId> <scope>test</test> <version>x.x.x</version> <!-- use the same version as your Camel core version --> </dependency>
Here is a simple unit test using the CamelCdiRunner
:
@RunWith(CamelCdiRunner.class) public class CamelCdiRunnerTest { @Inject CamelContext context; @Test public void test() { assertThat("Camel context status is incorrect!", context.getStatus(), is(equalTo(ServiceStatus.Started))); } }
CDI injection is also available for test method parameters, e.g.:
@RunWith(CamelCdiRunner.class) public class CamelCdiRunnerTest { @Test public void test(@Uri("direct:foo") ProducerTemplate producer) { producer.sendBody("bar"); } }
Camel CDI test provides the @Order
annotation that you can use to execute the test methods in a particular sequence, e.g.:
@RunWith(CamelCdiRunner.class) public class CamelCdiRunnerTest { @Test @Order(1) public void firstTestMethod() { } @Test @Order(2) public void secondTestMethod() { } }
One CDI container is bootstrapped for the entire execution of the test class.
Besides, the test class is deployed as a CDI bean, so that you can control how the runner instantiate the test class, either one test class instance for each test method (the default, depending on the built-in default @Dependent
CDI scope), or one test class instance for the entire test class execution using the @ApplicationScoped
scope, e.g.:
@ApplicationScoped @RunWith(CamelCdiRunner.class) public class CamelCdiRunnerTest { int counter; @Test @Order(1) public void firstTestMethod() { counter++; } @Test @Order(2) public void secondTestMethod() { assertEquals(counter, 1); } }
Arquillian
With this approach, you use the JUnit runner or TestNG support provided by Arquillian to delegate the bootstrap of the CDI container. You need to declare a @Deployment
method to create your application configuration to be deployed in the container using ShrinkWrap Descriptors, e.g.:
@RunWith(Arquillian.class) public class CamelCdiJavaSeTest { @Deployment public static Archive deployment() { return ShrinkWrap.create(JavaArchive.class) // Camel CDI .addPackage(CdiCamelExtension.class.getPackage()) // Test classes .addPackage(Application.class.getPackage()) // Bean archive deployment descriptor .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml"); } @Inject CamelContext context; @Test public void test() { assertThat("Camel context status is incorrect!", context.getStatus(), is(equalTo(ServiceStatus.Started))); } }
Using ShrinkWarp Descriptors, you have a complete control over the configuration and kind of Camel CDI applications you want to test. For example, to test a Camel CDI application that uses the Camel REST DSL configured with the Servlet component, you need to create a Web archive, e.g.:
@RunWith(Arquillian.class) public class CamelCdiWebTest { @Deployment public static Archive<?> createTestArchive() { return ShrinkWrap.create(WebArchive.class) .addClass(Application.class) .addAsWebInfResource(EmptyAsset.INSTANCE, ArchivePaths.create("beans.xml")) .setWebXML(Paths.get("src/main/webapp/WEB-INF/web.xml").toFile()); } @Test @RunAsClient public void test(@ArquillianResource URL url) throws Exception { assertThat(IOHelper.loadText(new URL(url, "camel/rest/hello").openStream()), is(equalTo("Hello World!\n"))); } }
PAX Exam
If your target OSGi as runtime environment for your Camel CDI applications, you can use PAX Exam to automate the deployment of your tests into an OSGi container, for example into Karaf, e.g.:
@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.
Testing
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, e.g.:
void advice(@Observes CamelContextStartingEvent event, @Uri("mock:test") MockEndpoint messages, ModelCamelContext context) throws Exception { context.getRouteDefinition("route") .adviceWith(context, new AdviceWithRouteBuilder() { @Override public void configure() { weaveAddLast().to("mock:test"); } }); }
JUnit rules
Camel CDI test starts the CDI container after all the JUnit class rules.