Test Spring JUnit5

Since Camel 3.0

The camel-test-spring-junit5 module is used for testing Camel with Spring; both the classic Spring XML files or Spring Boot.

Testing classic Spring XML

There are multiple approaches to test Camel Spring 5.x based routes with JUnit 5. An approach is to extend org.apache.camel.test.spring.junit5.CamelSpringTestSupport, for instance:

public class SimpleMockTest extends CamelSpringTestSupport {

    @EndpointInject("mock:result")
    protected MockEndpoint resultEndpoint;

    @Produce("direct:start")
    protected ProducerTemplate template;

    @Override
    protected AbstractApplicationContext createApplicationContext() {
        // loads a Spring XML file
        return new ClassPathXmlApplicationContext("org/apache/camel/test/patterns/SimpleMockTest.xml");
    }

    @Test
    public void testMock() throws Exception {
        String expectedBody = "Hello World";
        resultEndpoint.expectedBodiesReceived(expectedBody);
        template.sendBodyAndHeader(expectedBody, "foo", "bar");
        resultEndpoint.assertIsSatisfied();
    }
}

The example above is loading a classic Spring XML file (has <beans> as root tag).

This approach provides feature parity with org.apache.camel.test.junit5.CamelTestSupport from camel-test-junit5 but does not support Spring annotations on the test class such as @Autowired, @DirtiesContext, and @ContextConfiguration.

Instead of instantiating the CamelContext and routes programmatically, this class relies on a Spring context to wire the needed components together. If your test extends this class, you must provide the Spring context by implementing the following method:

protected abstract AbstractApplicationContext createApplicationContext();

Using the @CamelSpringTest annotation

A better and recommended approach involves the usage of the org.apache.camel.test.spring.junit5.CamelSpringTest annotation, as shown:

package com.foo;

@CamelSpringTest
@ContextConfiguration
@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)
public class CamelSpringPlainTest {

    @Autowired
    protected CamelContext camelContext;

    @EndpointInject("mock:a")
    protected MockEndpoint mockA;

    @EndpointInject("mock:b")
    protected MockEndpoint mockB;

    @Produce("direct:start")
    protected ProducerTemplate start;

    @Test
    public void testPositive() throws Exception {
        assertEquals(ServiceStatus.Started, camelContext.getStatus());

        mockA.expectedBodiesReceived("David");
        mockB.expectedBodiesReceived("Hello David");

        start.sendBody("David");

        MockEndpoint.assertIsSatisfied(camelContext);
    }
}

The above test will by default load a Spring XML file using the naming pattern className-context.xml, which means the example above loads the file com/foo/CamelSpringPlainTest-context.xml.

This XML file is Spring XML file as shown:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="
		http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd ">

	<camelContext id="camelContext" xmlns="http://camel.apache.org/schema/spring">
		<route>
			<from uri="direct:start"/>
			<to uri="mock:a"/>
			<transform>
				<simple>Hello ${body}</simple>
			</transform>
			<to uri="mock:b"/>
		</route>
	</camelContext>
</beans>

This approach supports both Camel and Spring annotations, such as @Autowired, @DirtiesContext, and @ContextConfiguration. However, it does NOT have feature parity with org.apache.camel.test.junit5.CamelTestSupport.

Camel test annotations

The following annotations can be used with camel-spring-junit5 unit testing.

Annotation Description

@CamelSpringBootTest

Used for testing Camel with Spring Boot

@CamelSpringTest

Used for testing Camel with classic Spring XML (not Spring Boot)

@DisableJmx

Used for disabling JMX

@EnableRouteCoverage

Enables dumping route coverage statistic. The route coverage status is written as xml files in the target/camel-route-coverage directory after the test has finished. See more information at Camel Maven Report Plugin.

@ExcludeRoutes

Indicates if certain route builder classes should be excluded from package scan discovery

@MockEndpoints

Auto-mocking of endpoints whose URIs match the provided filter. For more information see Advice With.

@MockEndpointsAndSkip

Auto-mocking of endpoints whose URIs match the provided filter with the added provision that the endpoints are also skipped. For more information see Advice With.

@ProvidesBreakpoint

Indicates that the annotated method returns a Breakpoint for use in the test. Useful for intercepting traffic to all endpoints or simply for setting a break point in an IDE for debugging. The method must be public static, take no arguments, and return Breakpoint.

@ShutdownTimeout

Timeout to use for shutdown. The default is 10 seconds.

@UseAdviceWith

To enable testing with Advice With.

@UseOverridePropertiesWithPropertiesComponent

To use custom Properties with the Properties component. The annotated method must be public and return Properties.

Migrating Camel Spring Tests from JUnit 4 to JUnit 5

Find below some hints to help in migrating Camel Spring tests from JUnit 4 to JUnit 5.

Projects using camel-test-spring would need to use camel-test-spring-junit5. For instance, maven users would update their pom.xml file as below:

<dependency>
  <groupId>org.apache.camel</groupId>
  <artifactId>camel-test-spring-junit5</artifactId>
  <scope>test</scope>
</dependency>
It’s possible to run JUnit 4 & JUnit 5 based Camel Spring tests side by side including the following dependencies camel-test-spring, camel-test-spring-junit5 and junit-vintage-engine. This configuration allows migrating Camel tests one by one.

Migration steps

  • Migration steps from camel-test-junit5 should have been applied first

  • Imports of org.apache.camel.test.spring.* should be replaced with org.apache.camel.test.spring.junit5.*

  • Usage of @RunWith(CamelSpringRunner.class) should be replaced with @CamelSpringTest

  • Usage of @BootstrapWith(CamelTestContextBootstrapper.class) should be replaced with @CamelSpringTest

  • Usage of @RunWith(CamelSpringBootRunner.class) should be replaced with @CamelSpringBootTest