You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by al...@apache.org on 2019/09/23 08:13:55 UTC
[camel] 01/02: CAMEL-13965: Created the camel-test-spring-junit5
based on camel-test-spring
This is an automated email from the ASF dual-hosted git repository.
aldettinger pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git
commit 564fbe1a341e99c498af7affbc055fd3af61b4a0
Author: aldettinger <al...@gmail.com>
AuthorDate: Wed Sep 11 10:15:41 2019 +0200
CAMEL-13965: Created the camel-test-spring-junit5 based on camel-test-spring
---
apache-camel/pom.xml | 5 +
apache-camel/src/main/descriptors/common-bin.xml | 1 +
bom/camel-bom/pom.xml | 5 +
components/camel-test-spring-junit5/pom.xml | 85 ++++
.../src/main/docs/test-spring-junit5.adoc | 140 ++++++
.../spring/junit5/CamelAnnotationsHandler.java | 367 ++++++++++++++
.../junit5/CamelSpringBootExecutionListener.java | 95 ++++
.../camel/test/spring/junit5/CamelSpringTest.java | 39 ++
.../junit5/CamelSpringTestContextLoader.java | 553 +++++++++++++++++++++
...ringTestContextLoaderTestExecutionListener.java | 50 ++
.../test/spring/junit5/CamelSpringTestHelper.java | 109 ++++
.../test/spring/junit5/CamelSpringTestSupport.java | 218 ++++++++
.../junit5/CamelTestContextBootstrapper.java | 31 ++
.../camel/test/spring/junit5/DisableJmx.java | 43 ++
.../junit5/DisableJmxTestExecutionListener.java | 39 ++
.../test/spring/junit5/EnableRouteCoverage.java | 41 ++
.../camel/test/spring/junit5/ExcludeRoutes.java | 44 ++
.../camel/test/spring/junit5/MockEndpoints.java | 43 ++
.../test/spring/junit5/MockEndpointsAndSkip.java | 43 ++
.../test/spring/junit5/ProvidesBreakpoint.java | 36 ++
.../test/spring/junit5/RouteCoverageDumper.java | 82 +++
.../spring/junit5/RouteCoverageEventNotifier.java | 50 ++
.../camel/test/spring/junit5/ShutdownTimeout.java | 49 ++
.../junit5/StopWatchTestExecutionListener.java | 62 +++
.../camel/test/spring/junit5/UseAdviceWith.java | 49 ++
...eOverridePropertiesWithPropertiesComponent.java | 34 ++
...nterceptSendToEndpointWithLoadbalancerTest.java | 68 +++
.../test/issues/AdviceWithOnCompletionTest.java | 61 +++
.../AdviceWithOnExceptionMultipleIssueTest.java | 114 +++++
.../test/issues/MockEndpointsAndSkipTest.java | 46 ++
.../test/patterns/DebugSpringCamelContextTest.java | 40 ++
.../camel/test/patterns/DebugSpringTest.java | 87 ++++
.../apache/camel/test/patterns/MyProduceBean.java | 38 ++
.../org/apache/camel/test/patterns/MySender.java | 22 +
.../camel/test/patterns/ProduceBeanTest.java | 39 ++
.../test/patterns/ProducerBeanInjectTest.java | 40 ++
.../apache/camel/test/patterns/SimpleMockTest.java | 63 +++
.../test/spring/CamelSpringActiveProfileTest.java | 57 +++
...CamelSpringDisableJmxInheritedOverrideTest.java | 34 ++
.../spring/CamelSpringDisableJmxInheritedTest.java | 21 +
.../test/spring/CamelSpringDisableJmxTest.java | 34 ++
.../test/spring/CamelSpringExcludeRoutesTest.java | 33 ++
...ingOverridePropertiesForPropertyInjectTest.java | 56 +++
.../spring/CamelSpringOverridePropertiesTest.java | 71 +++
.../camel/test/spring/CamelSpringPlainTest.java | 111 +++++
.../CamelSpringPropertiesLocationElementTest.java | 65 +++
...amelSpringProvidesBreakpointInherritedTest.java | 22 +
.../spring/CamelSpringProvidesBreakpointTest.java | 67 +++
...lSpringRouteProcessorDumpRouteCoverageTest.java | 56 +++
...SpringShutdownTimeoutInheritedOverrideTest.java | 36 ++
.../CamelSpringShutdownTimeoutInheritedTest.java | 22 +
.../spring/CamelSpringShutdownTimeoutTest.java | 36 ++
.../spring/CamelSpringTestPropertySourceTest.java | 47 ++
.../CamelSpringTestSupportActiveProfileTest.java | 52 ++
.../test/spring/CamelSpringUseAdviceWithTest.java | 52 ++
.../spring/TestPropertyInjectRouteBuilder.java | 33 ++
.../apache/camel/test/spring/TestRouteBuilder.java | 29 ++
.../src/test/resources/jndi.properties | 22 +
.../src/test/resources/log4j2.properties | 30 ++
...InterceptSendToEndpointWithLoadbalancerTest.xml | 34 ++
.../test/issues/AdviceWithOnCompletionTest.xml | 40 ++
.../AdviceWithOnExceptionMultipleIssueTest.xml | 50 ++
.../camel/test/issues/MockEndpointsAndSkipTest.xml | 38 ++
.../camel/test/patterns/ProduceBeanInjectTest.xml | 44 ++
.../apache/camel/test/patterns/ProduceBeanTest.xml | 36 ++
.../apache/camel/test/patterns/SimpleMockTest.xml | 34 ++
.../camel/test/patterns/applicationContext.xml | 42 ++
.../CamelSpringActiveProfileTest-context.xml | 46 ++
...ridePropertiesForPropertyInjectTest-context.xml | 40 ++
.../CamelSpringOverridePropertiesTest-context.xml | 45 ++
.../test/spring/CamelSpringPlainTest-context.xml | 48 ++
...SpringPropertiesLocationElementTest-context.xml | 56 +++
.../CamelSpringTestPropertySourceTest-context.xml | 44 ++
.../properties-location-element-1.properties | 18 +
.../properties-location-element-2.properties | 18 +
.../properties-location-element-3.properties | 18 +
.../org/apache/camel/test/spring/test.properties | 19 +
components/pom.xml | 1 +
docs/components/modules/ROOT/nav.adoc | 1 +
.../modules/ROOT/pages/test-spring-junit5.adoc | 141 ++++++
parent/pom.xml | 5 +
.../camel-spring-boot-dependencies/pom.xml | 5 +
82 files changed, 4740 insertions(+)
diff --git a/apache-camel/pom.xml b/apache-camel/pom.xml
index cd49209..4b55220 100644
--- a/apache-camel/pom.xml
+++ b/apache-camel/pom.xml
@@ -1508,6 +1508,11 @@
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
+ <artifactId>camel-test-spring-junit5</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
<artifactId>camel-test-karaf</artifactId>
<version>${project.version}</version>
</dependency>
diff --git a/apache-camel/src/main/descriptors/common-bin.xml b/apache-camel/src/main/descriptors/common-bin.xml
index a6312b3..09eaa00 100644
--- a/apache-camel/src/main/descriptors/common-bin.xml
+++ b/apache-camel/src/main/descriptors/common-bin.xml
@@ -322,6 +322,7 @@
<include>org.apache.camel:camel-test-blueprint</include>
<include>org.apache.camel:camel-test-cdi</include>
<include>org.apache.camel:camel-test-junit5</include>
+ <include>org.apache.camel:camel-test-spring-junit5</include>
<include>org.apache.camel:camel-test-karaf</include>
<include>org.apache.camel:camel-test-spring</include>
<include>org.apache.camel:camel-testcontainers</include>
diff --git a/bom/camel-bom/pom.xml b/bom/camel-bom/pom.xml
index ec9ce5f..52b2c0f 100644
--- a/bom/camel-bom/pom.xml
+++ b/bom/camel-bom/pom.xml
@@ -2925,6 +2925,11 @@
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
+ <artifactId>camel-test-spring-junit5</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
<artifactId>camel-test-karaf</artifactId>
<version>${project.version}</version>
</dependency>
diff --git a/components/camel-test-spring-junit5/pom.xml b/components/camel-test-spring-junit5/pom.xml
new file mode 100644
index 0000000..49deb7c
--- /dev/null
+++ b/components/camel-test-spring-junit5/pom.xml
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>components</artifactId>
+ <version>3.0.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>camel-test-spring-junit5</artifactId>
+ <packaging>jar</packaging>
+
+ <name>Camel :: Test :: Spring:: JUnit5</name>
+ <description>Camel unit testing with Spring and JUnit 5</description>
+
+ <properties>
+ <firstVersion>3.0.0</firstVersion>
+ <label>testing,java,spring</label>
+
+ <spring-version>${spring5-version}</spring-version>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-test-junit5</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-spring</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-test</artifactId>
+ </dependency>
+
+ <!-- test dependencies -->
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-management</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.logging.log4j</groupId>
+ <artifactId>log4j-api</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.logging.log4j</groupId>
+ <artifactId>log4j-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.logging.log4j</groupId>
+ <artifactId>log4j-slf4j-impl</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/components/camel-test-spring-junit5/src/main/docs/test-spring-junit5.adoc b/components/camel-test-spring-junit5/src/main/docs/test-spring-junit5.adoc
new file mode 100644
index 0000000..58717f0
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/main/docs/test-spring-junit5.adoc
@@ -0,0 +1,140 @@
+= Camel Test Spring JUnit 5
+
+*Available since 3.0*
+
+The `camel-test-spring-junit5` module makes it possible to test Camel Spring based applications with JUnit 5.
+
+Testing is a crucial part of any development or integration work. The Spring Framework offers a number of features that makes it easy to test while using Spring for Inversion of Control.
+
+There are multiple approaches to test Camel Spring 5.x based routes with JUnit 5.
+
+== Extending the CamelSpringTestSupport class
+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() {
+ 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();
+ }
+}
+----
+
+This approach provides feature parity with `org.apache.camel.test.junit5.CamelTestSupport` from xref:components::test-junit5.adoc[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.
+[source,java]
+----
+protected abstract AbstractApplicationContext createApplicationContext();
+----
+
+== Using the @CamelSpringTest annotation
+Another approach involves the usage of the `org.apache.camel.test.spring.junit5.CamelSpringTest` annotation, for instance:
+----
+@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);
+ }
+
+ @Test
+ public void testAnotherCase() throws Exception {
+ ...
+ }
+}
+----
+
+The above test will load the route from `org/apache/camel/test/spring/CamelSpringPlainTest-context.xml` which looks like below:
+----
+<?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" trace="true"
+ autoStartup="true">
+ <packageScan>
+ <package>org.apache.camel.test.spring</package>
+ </packageScan>
+ <route>
+ <from uri="direct:start" />
+ <to uri="mock:a" />
+ <transform>
+ <simple>Hello ${body}</simple>
+ </transform>
+ <to uri="mock:b" />
+ </route>
+ </camelContext>
+
+ <bean id="bridgePropertyPlaceholder"
+ class="org.apache.camel.spring.spi.BridgePropertyPlaceholderConfigurer">
+ <property name="location"
+ value="classpath:org/apache/camel/test/spring/test.properties" />
+ </bean>
+</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`.
+
+== 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.
+
+=== Referencing the Camel Test Spring JUnit 5 library in your project
+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>
+----
+
+Tips: 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 to migrate a Camel Spring test at once.
+
+=== Typical migration steps linked to JUnit 5 support in Camel Test Spring
+* Migration steps linked to xref:components::test-junit5.adoc[JUnit 5 support in Camel Test itself] 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`
diff --git a/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/CamelAnnotationsHandler.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/CamelAnnotationsHandler.java
new file mode 100644
index 0000000..84052ec
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/CamelAnnotationsHandler.java
@@ -0,0 +1,367 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.spring.junit5;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Properties;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Function;
+
+import org.apache.camel.ExtendedCamelContext;
+import org.apache.camel.api.management.JmxSystemPropertyKeys;
+import org.apache.camel.api.management.ManagedCamelContext;
+import org.apache.camel.api.management.mbean.ManagedCamelContextMBean;
+import org.apache.camel.component.properties.PropertiesComponent;
+import org.apache.camel.impl.engine.InterceptSendToMockEndpointStrategy;
+import org.apache.camel.processor.interceptor.DefaultDebugger;
+import org.apache.camel.spi.Breakpoint;
+import org.apache.camel.spi.Debugger;
+import org.apache.camel.spi.EventNotifier;
+import org.apache.camel.spring.SpringCamelContext;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.apache.camel.util.CollectionStringBuffer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.core.annotation.AnnotationUtils;
+
+import static org.apache.camel.test.spring.junit5.CamelSpringTestHelper.getAllMethods;
+
+public final class CamelAnnotationsHandler {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(CamelAnnotationsHandler.class);
+
+ private CamelAnnotationsHandler() {
+ }
+
+ /**
+ * Handles @ExcludeRoutes to make it easier to exclude other routes when testing with Spring Boot.
+ *
+ * @param testClass the test class being executed
+ */
+ public static void handleExcludeRoutesForSpringBoot(Class<?> testClass) {
+ if (testClass.isAnnotationPresent(ExcludeRoutes.class)) {
+ Class[] routes = testClass.getAnnotation(ExcludeRoutes.class).value();
+ // need to setup this as a JVM system property
+ CollectionStringBuffer csb = new CollectionStringBuffer(",");
+ for (Class clazz : routes) {
+ csb.append(clazz.getName());
+ }
+ String key = "CamelTestSpringExcludeRoutes";
+ String value = csb.toString();
+
+ String exists = System.getProperty(key);
+ if (exists != null) {
+ LOGGER.warn("Cannot use @ExcludeRoutes as JVM property " + key + " has already been set.");
+ } else {
+ LOGGER.info("@ExcludeRoutes annotation found. Setting up JVM property {}={}", key, value);
+ System.setProperty(key, value);
+ }
+ }
+ }
+
+ /**
+ * Handles disabling of JMX on Camel contexts based on {@link DisableJmx}.
+ *
+ * @param context the initialized Spring context
+ * @param testClass the test class being executed
+ */
+ public static void handleDisableJmx(ConfigurableApplicationContext context, Class<?> testClass) {
+ CamelSpringTestHelper.setOriginalJmxDisabledValue(System.getProperty(JmxSystemPropertyKeys.DISABLED));
+
+ if (testClass.isAnnotationPresent(DisableJmx.class)) {
+ if (testClass.getAnnotation(DisableJmx.class).value()) {
+ LOGGER.info("Disabling Camel JMX globally as DisableJmx annotation was found and disableJmx is set to true.");
+ System.setProperty(JmxSystemPropertyKeys.DISABLED, "true");
+
+ } else {
+ LOGGER.info("Enabling Camel JMX as DisableJmx annotation was found and disableJmx is set to false.");
+ System.clearProperty(JmxSystemPropertyKeys.DISABLED);
+ }
+ } else {
+ LOGGER.info("Disabling Camel JMX globally for tests by default. Use the DisableJMX annotation to override the default setting.");
+ System.setProperty(JmxSystemPropertyKeys.DISABLED, "true");
+ }
+ }
+
+ /**
+ * Handles disabling of JMX on Camel contexts based on {@link DisableJmx}.
+ *
+ * @param context the initialized Spring context
+ * @param testClass the test class being executed
+ */
+ public static void handleRouteCoverage(ConfigurableApplicationContext context, Class<?> testClass, Function testMethod) throws Exception {
+ if (testClass.isAnnotationPresent(EnableRouteCoverage.class)) {
+ System.setProperty(CamelTestSupport.ROUTE_COVERAGE_ENABLED, "true");
+
+ CamelSpringTestHelper.doToSpringCamelContexts(context, new CamelSpringTestHelper.DoToSpringCamelContextsStrategy() {
+
+ @Override
+ public void execute(String contextName, SpringCamelContext camelContext) throws Exception {
+ LOGGER.info("Enabling RouteCoverage");
+ EventNotifier notifier = new RouteCoverageEventNotifier(testClass.getName(), testMethod);
+ camelContext.addService(notifier, true);
+ camelContext.getManagementStrategy().addEventNotifier(notifier);
+ }
+ });
+ }
+ }
+
+ public static void handleRouteCoverageDump(ConfigurableApplicationContext context, Class<?> testClass, Function testMethod) throws Exception {
+ if (testClass.isAnnotationPresent(EnableRouteCoverage.class)) {
+ CamelSpringTestHelper.doToSpringCamelContexts(context, new CamelSpringTestHelper.DoToSpringCamelContextsStrategy() {
+
+ @Override
+ public void execute(String contextName, SpringCamelContext camelContext) throws Exception {
+ LOGGER.debug("Dumping RouteCoverage");
+
+ String testMethodName = (String) testMethod.apply(this);
+ RouteCoverageDumper.dumpRouteCoverage(camelContext, testClass.getName(), testMethodName);
+
+ // reset JMX statistics
+ ManagedCamelContextMBean managedCamelContext = camelContext.getExtension(ManagedCamelContext.class).getManagedCamelContext();
+ if (managedCamelContext != null) {
+ LOGGER.debug("Resetting JMX statistics for RouteCoverage");
+ managedCamelContext.reset(true);
+ }
+
+ // turn off dumping one more time by removing the event listener (which would dump as well when Camel is stopping)
+ // but this method was explicit invoked to dump such as from afterTest callbacks from JUnit.
+ RouteCoverageEventNotifier eventNotifier = camelContext.hasService(RouteCoverageEventNotifier.class);
+ if (eventNotifier != null) {
+ camelContext.getManagementStrategy().removeEventNotifier(eventNotifier);
+ camelContext.removeService(eventNotifier);
+ }
+ }
+ });
+ }
+ }
+
+ public static void handleProvidesBreakpoint(ConfigurableApplicationContext context, Class<?> testClass) throws Exception {
+ Collection<Method> methods = getAllMethods(testClass);
+ final List<Breakpoint> breakpoints = new LinkedList<>();
+
+ for (Method method : methods) {
+ if (AnnotationUtils.findAnnotation(method, ProvidesBreakpoint.class) != null) {
+ Class<?>[] argTypes = method.getParameterTypes();
+ if (argTypes.length != 0) {
+ throw new IllegalArgumentException("Method [" + method.getName()
+ + "] is annotated with ProvidesBreakpoint but is not a no-argument method.");
+ } else if (!Breakpoint.class.isAssignableFrom(method.getReturnType())) {
+ throw new IllegalArgumentException("Method [" + method.getName()
+ + "] is annotated with ProvidesBreakpoint but does not return a Breakpoint.");
+ } else if (!Modifier.isStatic(method.getModifiers())) {
+ throw new IllegalArgumentException("Method [" + method.getName()
+ + "] is annotated with ProvidesBreakpoint but is not static.");
+ } else if (!Modifier.isPublic(method.getModifiers())) {
+ throw new IllegalArgumentException("Method [" + method.getName()
+ + "] is annotated with ProvidesBreakpoint but is not public.");
+ }
+
+ try {
+ breakpoints.add((Breakpoint) method.invoke(null));
+ } catch (Exception e) {
+ throw new RuntimeException("Method [" + method.getName()
+ + "] threw exception during evaluation.", e);
+ }
+ }
+ }
+
+ if (breakpoints.size() != 0) {
+ CamelSpringTestHelper.doToSpringCamelContexts(context, new CamelSpringTestHelper.DoToSpringCamelContextsStrategy() {
+
+ public void execute(String contextName, SpringCamelContext camelContext)
+ throws Exception {
+ Debugger debugger = camelContext.getDebugger();
+ if (debugger == null) {
+ debugger = new DefaultDebugger();
+ camelContext.setDebugger(debugger);
+ }
+
+ for (Breakpoint breakpoint : breakpoints) {
+ LOGGER.info("Adding Breakpoint [{}] to CamelContext with name [{}].", breakpoint, contextName);
+ debugger.addBreakpoint(breakpoint);
+ }
+ }
+ });
+ }
+ }
+
+ /**
+ * Handles updating shutdown timeouts on Camel contexts based on {@link ShutdownTimeout}.
+ *
+ * @param context the initialized Spring context
+ * @param testClass the test class being executed
+ */
+ public static void handleShutdownTimeout(ConfigurableApplicationContext context, Class<?> testClass) throws Exception {
+ final int shutdownTimeout;
+ final TimeUnit shutdownTimeUnit;
+ if (testClass.isAnnotationPresent(ShutdownTimeout.class)) {
+ shutdownTimeout = testClass.getAnnotation(ShutdownTimeout.class).value();
+ shutdownTimeUnit = testClass.getAnnotation(ShutdownTimeout.class).timeUnit();
+ } else {
+ shutdownTimeout = 10;
+ shutdownTimeUnit = TimeUnit.SECONDS;
+ }
+
+ CamelSpringTestHelper.doToSpringCamelContexts(context, new CamelSpringTestHelper.DoToSpringCamelContextsStrategy() {
+
+ public void execute(String contextName, SpringCamelContext camelContext)
+ throws Exception {
+ LOGGER.info("Setting shutdown timeout to [{} {}] on CamelContext with name [{}].", shutdownTimeout, shutdownTimeUnit, contextName);
+ camelContext.getShutdownStrategy().setTimeout(shutdownTimeout);
+ camelContext.getShutdownStrategy().setTimeUnit(shutdownTimeUnit);
+ }
+ });
+ }
+
+ /**
+ * Handles auto-intercepting of endpoints with mocks based on {@link MockEndpoints}.
+ *
+ * @param context the initialized Spring context
+ * @param testClass the test class being executed
+ */
+ public static void handleMockEndpoints(ConfigurableApplicationContext context, Class<?> testClass) throws Exception {
+ if (testClass.isAnnotationPresent(MockEndpoints.class)) {
+ final String mockEndpoints = testClass.getAnnotation(MockEndpoints.class).value();
+ CamelSpringTestHelper.doToSpringCamelContexts(context, new CamelSpringTestHelper.DoToSpringCamelContextsStrategy() {
+
+ public void execute(String contextName, SpringCamelContext camelContext)
+ throws Exception {
+ LOGGER.info("Enabling auto mocking of endpoints matching pattern [{}] on CamelContext with name [{}].", mockEndpoints, contextName);
+ camelContext.adapt(ExtendedCamelContext.class).registerEndpointCallback(new InterceptSendToMockEndpointStrategy(mockEndpoints));
+ }
+ });
+ }
+ }
+
+ /**
+ * Handles auto-intercepting of endpoints with mocks based on {@link MockEndpointsAndSkip} and skipping the
+ * original endpoint.
+ *
+ * @param context the initialized Spring context
+ * @param testClass the test class being executed
+ */
+ public static void handleMockEndpointsAndSkip(ConfigurableApplicationContext context, Class<?> testClass) throws Exception {
+ if (testClass.isAnnotationPresent(MockEndpointsAndSkip.class)) {
+ final String mockEndpoints = testClass.getAnnotation(MockEndpointsAndSkip.class).value();
+ CamelSpringTestHelper.doToSpringCamelContexts(context, new CamelSpringTestHelper.DoToSpringCamelContextsStrategy() {
+
+ public void execute(String contextName, SpringCamelContext camelContext)
+ throws Exception {
+ // resolve the property place holders of the mockEndpoints
+ String mockEndpointsValue = camelContext.resolvePropertyPlaceholders(mockEndpoints);
+ LOGGER.info("Enabling auto mocking and skipping of endpoints matching pattern [{}] on CamelContext with name [{}].", mockEndpointsValue, contextName);
+ camelContext.adapt(ExtendedCamelContext.class).registerEndpointCallback(new InterceptSendToMockEndpointStrategy(mockEndpointsValue, true));
+ }
+ });
+ }
+ }
+
+ /**
+ * Handles override this method to include and override properties with the Camel {@link org.apache.camel.component.properties.PropertiesComponent}.
+ *
+ * @param context the initialized Spring context
+ * @param testClass the test class being executed
+ */
+ public static void handleUseOverridePropertiesWithPropertiesComponent(ConfigurableApplicationContext context, Class<?> testClass) throws Exception {
+ Collection<Method> methods = getAllMethods(testClass);
+ final List<Properties> properties = new LinkedList<>();
+
+ for (Method method : methods) {
+ if (AnnotationUtils.findAnnotation(method, UseOverridePropertiesWithPropertiesComponent.class) != null) {
+ Class<?>[] argTypes = method.getParameterTypes();
+ if (argTypes.length > 0) {
+ throw new IllegalArgumentException("Method [" + method.getName()
+ + "] is annotated with UseOverridePropertiesWithPropertiesComponent but is not a no-argument method.");
+ } else if (!Properties.class.isAssignableFrom(method.getReturnType())) {
+ throw new IllegalArgumentException("Method [" + method.getName()
+ + "] is annotated with UseOverridePropertiesWithPropertiesComponent but does not return a java.util.Properties.");
+ } else if (!Modifier.isStatic(method.getModifiers())) {
+ throw new IllegalArgumentException("Method [" + method.getName()
+ + "] is annotated with UseOverridePropertiesWithPropertiesComponent but is not static.");
+ } else if (!Modifier.isPublic(method.getModifiers())) {
+ throw new IllegalArgumentException("Method [" + method.getName()
+ + "] is annotated with UseOverridePropertiesWithPropertiesComponent but is not public.");
+ }
+
+ try {
+ properties.add((Properties) method.invoke(null));
+ } catch (Exception e) {
+ throw new RuntimeException("Method [" + method.getName()
+ + "] threw exception during evaluation.", e);
+ }
+ }
+ }
+
+ if (properties.size() != 0) {
+ CamelSpringTestHelper.doToSpringCamelContexts(context, new CamelSpringTestHelper.DoToSpringCamelContextsStrategy() {
+ public void execute(String contextName, SpringCamelContext camelContext) throws Exception {
+ PropertiesComponent pc = camelContext.getComponent("properties", PropertiesComponent.class);
+ Properties extra = new Properties();
+ for (Properties prop : properties) {
+ extra.putAll(prop);
+ }
+ if (!extra.isEmpty()) {
+ LOGGER.info("Using {} properties to override any existing properties on the PropertiesComponent on CamelContext with name [{}].", extra.size(), contextName);
+ pc.setOverrideProperties(extra);
+ }
+ }
+ });
+ }
+ }
+
+ /**
+ * Handles starting of Camel contexts based on {@link UseAdviceWith} and other state in the JVM.
+ *
+ * @param context the initialized Spring context
+ * @param testClass the test class being executed
+ */
+ public static void handleCamelContextStartup(ConfigurableApplicationContext context, Class<?> testClass) throws Exception {
+ boolean skip = "true".equalsIgnoreCase(System.getProperty("skipStartingCamelContext"));
+ if (skip) {
+ LOGGER.info("Skipping starting CamelContext(s) as system property skipStartingCamelContext is set to be true.");
+ } else if (testClass.isAnnotationPresent(UseAdviceWith.class)) {
+ if (testClass.getAnnotation(UseAdviceWith.class).value()) {
+ LOGGER.info("Skipping starting CamelContext(s) as UseAdviceWith annotation was found and isUseAdviceWith is set to true.");
+ skip = true;
+ } else {
+ LOGGER.info("Starting CamelContext(s) as UseAdviceWith annotation was found, but isUseAdviceWith is set to false.");
+ skip = false;
+ }
+ }
+
+ if (!skip) {
+ CamelSpringTestHelper.doToSpringCamelContexts(context, new CamelSpringTestHelper.DoToSpringCamelContextsStrategy() {
+ public void execute(String contextName,
+ SpringCamelContext camelContext) throws Exception {
+ if (!camelContext.isStarted()) {
+ LOGGER.info("Starting CamelContext with name [{}].", contextName);
+ camelContext.start();
+ } else {
+ LOGGER.debug("CamelContext with name [{}] already started.", contextName);
+ }
+ }
+ });
+ }
+ }
+
+}
diff --git a/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/CamelSpringBootExecutionListener.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/CamelSpringBootExecutionListener.java
new file mode 100644
index 0000000..41deaf7
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/CamelSpringBootExecutionListener.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.spring.junit5;
+
+import org.apache.camel.spring.SpringCamelContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.test.context.TestContext;
+import org.springframework.test.context.support.AbstractTestExecutionListener;
+
+public class CamelSpringBootExecutionListener extends AbstractTestExecutionListener {
+
+ protected static ThreadLocal<ConfigurableApplicationContext> threadApplicationContext = new ThreadLocal<>();
+
+ private static final Logger LOG = LoggerFactory.getLogger(CamelSpringBootExecutionListener.class);
+
+ @Override
+ public void prepareTestInstance(TestContext testContext) throws Exception {
+ LOG.info("CamelSpringBootExecutionListener preparing: {}", testContext.getTestClass());
+
+ Class<?> testClass = testContext.getTestClass();
+
+ // need to prepare this before we load spring application context
+ CamelAnnotationsHandler.handleExcludeRoutesForSpringBoot(testClass);
+
+ // we are customizing the Camel context with
+ // CamelAnnotationsHandler so we do not want to start it
+ // automatically, which would happen when SpringCamelContext
+ // is added to Spring ApplicationContext, so we set the flag
+ // not to start it just yet
+ SpringCamelContext.setNoStart(true);
+ System.setProperty("skipStartingCamelContext", "true");
+ ConfigurableApplicationContext context = (ConfigurableApplicationContext) testContext.getApplicationContext();
+
+ // Post CamelContext(s) instantiation but pre CamelContext(s) start setup
+ CamelAnnotationsHandler.handleProvidesBreakpoint(context, testClass);
+ CamelAnnotationsHandler.handleShutdownTimeout(context, testClass);
+ CamelAnnotationsHandler.handleMockEndpoints(context, testClass);
+ CamelAnnotationsHandler.handleMockEndpointsAndSkip(context, testClass);
+ CamelAnnotationsHandler.handleUseOverridePropertiesWithPropertiesComponent(context, testClass);
+
+ System.clearProperty("skipStartingCamelContext");
+ SpringCamelContext.setNoStart(false);
+ }
+
+ @Override
+ public void beforeTestMethod(TestContext testContext) throws Exception {
+ LOG.info("CamelSpringBootExecutionListener before: {}.{}", testContext.getTestClass(), testContext.getTestMethod().getName());
+
+ Class<?> testClass = testContext.getTestClass();
+ String testName = testContext.getTestMethod().getName();
+
+ ConfigurableApplicationContext context = (ConfigurableApplicationContext) testContext.getApplicationContext();
+ threadApplicationContext.set(context);
+
+ // mark Camel to be startable again and start Camel
+ System.clearProperty("skipStartingCamelContext");
+
+ // route coverage need to know the test method
+ CamelAnnotationsHandler.handleRouteCoverage(context, testClass, s -> testName);
+
+ LOG.info("Initialized CamelSpringBootExecutionListener now ready to start CamelContext");
+ CamelAnnotationsHandler.handleCamelContextStartup(context, testClass);
+ }
+
+ @Override
+ public void afterTestMethod(TestContext testContext) throws Exception {
+ LOG.info("CamelSpringBootExecutionListener after: {}.{}", testContext.getTestClass(), testContext.getTestMethod().getName());
+
+ Class<?> testClass = testContext.getTestClass();
+ String testName = testContext.getTestMethod().getName();
+
+ ConfigurableApplicationContext context = threadApplicationContext.get();
+ if (context != null && context.isRunning()) {
+ // dump route coverage for each test method so its accurate statistics
+ // even if spring application context is running (i.e. its not dirtied per test method)
+ CamelAnnotationsHandler.handleRouteCoverageDump(context, testClass, s -> testName);
+ }
+ }
+}
diff --git a/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/CamelSpringTest.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/CamelSpringTest.java
new file mode 100644
index 0000000..5049a57
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/CamelSpringTest.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.spring.junit5;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.test.context.BootstrapWith;
+import org.springframework.test.context.TestExecutionListeners;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE})
+@ExtendWith(SpringExtension.class)
+@BootstrapWith(CamelTestContextBootstrapper.class)
+@TestExecutionListeners(value = {CamelSpringTestContextLoaderTestExecutionListener.class, DisableJmxTestExecutionListener.class,
+ StopWatchTestExecutionListener.class}, mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS)
+public @interface CamelSpringTest {
+
+}
\ No newline at end of file
diff --git a/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/CamelSpringTestContextLoader.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/CamelSpringTestContextLoader.java
new file mode 100644
index 0000000..50c0be2
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/CamelSpringTestContextLoader.java
@@ -0,0 +1,553 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.spring.junit5;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Properties;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.ExtendedCamelContext;
+import org.apache.camel.api.management.JmxSystemPropertyKeys;
+import org.apache.camel.impl.engine.InterceptSendToMockEndpointStrategy;
+import org.apache.camel.processor.interceptor.DefaultDebugger;
+import org.apache.camel.spi.Breakpoint;
+import org.apache.camel.spi.Debugger;
+import org.apache.camel.spi.EventNotifier;
+import org.apache.camel.spi.PropertiesComponent;
+import org.apache.camel.spring.SpringCamelContext;
+import org.apache.camel.test.ExcludingPackageScanClassResolver;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.apache.camel.test.spring.junit5.CamelSpringTestHelper.DoToSpringCamelContextsStrategy;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.config.BeanPostProcessor;
+import org.springframework.beans.factory.support.RootBeanDefinition;
+import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.context.annotation.AnnotationConfigUtils;
+import org.springframework.context.support.GenericApplicationContext;
+import org.springframework.core.annotation.AnnotationUtils;
+import org.springframework.test.context.MergedContextConfiguration;
+import org.springframework.test.context.support.AbstractContextLoader;
+import org.springframework.test.context.support.AbstractGenericContextLoader;
+import org.springframework.test.context.support.GenericXmlContextLoader;
+import org.springframework.util.StringUtils;
+
+import static org.apache.camel.test.spring.junit5.CamelSpringTestHelper.getAllMethods;
+
+/**
+ * Replacement for the default {@link GenericXmlContextLoader} that provides hooks for
+ * processing some class level Camel related test annotations.
+ */
+public class CamelSpringTestContextLoader extends AbstractContextLoader {
+
+ private static final Logger LOG = LoggerFactory.getLogger(CamelSpringTestContextLoader.class);
+
+ /**
+ * Modeled after the Spring implementation in {@link AbstractGenericContextLoader},
+ * this method creates and refreshes the application context while providing for
+ * processing of additional Camel specific post-refresh actions. We do not provide the
+ * pre-post hooks for customization seen in {@link AbstractGenericContextLoader} because
+ * they probably are unnecessary for 90+% of users.
+ * <p/>
+ * For some functionality, we cannot use {@link org.springframework.test.context.TestExecutionListener} because we need
+ * to both produce the desired outcome during application context loading, and also cleanup
+ * after ourselves even if the test class never executes. Thus the listeners, which
+ * only run if the application context is successfully initialized are insufficient to
+ * provide the behavior described above.
+ */
+ @Override
+ public ApplicationContext loadContext(MergedContextConfiguration mergedConfig) throws Exception {
+ Class<?> testClass = getTestClass();
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Loading ApplicationContext for merged context configuration [{}].", mergedConfig);
+ }
+
+ try {
+ GenericApplicationContext context = createContext(testClass, mergedConfig);
+ prepareContext(context, mergedConfig);
+ loadBeanDefinitions(context, mergedConfig);
+ return loadContext(context, testClass);
+ } finally {
+ cleanup(testClass);
+ }
+ }
+
+ /**
+ * Modeled after the Spring implementation in {@link AbstractGenericContextLoader},
+ * this method creates and refreshes the application context while providing for
+ * processing of additional Camel specific post-refresh actions. We do not provide the
+ * pre-post hooks for customization seen in {@link AbstractGenericContextLoader} because
+ * they probably are unnecessary for 90+% of users.
+ * <p/>
+ * For some functionality, we cannot use {@link org.springframework.test.context.TestExecutionListener} because we need
+ * to both produce the desired outcome during application context loading, and also cleanup
+ * after ourselves even if the test class never executes. Thus the listeners, which
+ * only run if the application context is successfully initialized are insufficient to
+ * provide the behavior described above.
+ */
+ @Override
+ public ApplicationContext loadContext(String... locations) throws Exception {
+
+ Class<?> testClass = getTestClass();
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Loading ApplicationContext for locations [" + StringUtils.arrayToCommaDelimitedString(locations) + "].");
+ }
+
+ try {
+ GenericApplicationContext context = createContext(testClass, null);
+ loadBeanDefinitions(context, locations);
+ return loadContext(context, testClass);
+ } finally {
+ cleanup(testClass);
+ }
+ }
+
+ /**
+ * Returns "<code>-context.xml</code>".
+ */
+ @Override
+ public String getResourceSuffix() {
+ return "-context.xml";
+ }
+
+ /**
+ * Performs the bulk of the Spring application context loading/customization.
+ *
+ * @param context the partially configured context. The context should have the bean definitions loaded, but nothing else.
+ * @param testClass the test class being executed
+ * @return the initialized (refreshed) Spring application context
+ *
+ * @throws Exception if there is an error during initialization/customization
+ */
+ protected ApplicationContext loadContext(GenericApplicationContext context, Class<?> testClass) throws Exception {
+
+ AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
+
+ // Pre CamelContext(s) instantiation setup
+ handleDisableJmx(context, testClass);
+ handleUseOverridePropertiesWithPropertiesComponent(context, testClass);
+
+ // Temporarily disable CamelContext start while the contexts are instantiated.
+ SpringCamelContext.setNoStart(true);
+ context.refresh();
+ context.registerShutdownHook();
+ // Turn CamelContext startup back on since the context's have now been instantiated.
+ SpringCamelContext.setNoStart(false);
+
+ // Post CamelContext(s) instantiation but pre CamelContext(s) start setup
+ handleRouteCoverage(context, testClass);
+ handleProvidesBreakpoint(context, testClass);
+ handleShutdownTimeout(context, testClass);
+ handleMockEndpoints(context, testClass);
+ handleMockEndpointsAndSkip(context, testClass);
+
+ // CamelContext(s) startup
+ handleCamelContextStartup(context, testClass);
+
+ return context;
+ }
+
+ /**
+ * Cleanup/restore global state to defaults / pre-test values after the test setup
+ * is complete.
+ *
+ * @param testClass the test class being executed
+ */
+ protected void cleanup(Class<?> testClass) {
+ SpringCamelContext.setNoStart(false);
+
+ if (testClass.isAnnotationPresent(DisableJmx.class)) {
+ if (CamelSpringTestHelper.getOriginalJmxDisabled() == null) {
+ System.clearProperty(JmxSystemPropertyKeys.DISABLED);
+ } else {
+ System.setProperty(JmxSystemPropertyKeys.DISABLED,
+ CamelSpringTestHelper.getOriginalJmxDisabled());
+ }
+ }
+ }
+
+ protected void loadBeanDefinitions(GenericApplicationContext context, MergedContextConfiguration mergedConfig) {
+ (new XmlBeanDefinitionReader(context)).loadBeanDefinitions(mergedConfig.getLocations());
+ }
+
+ protected void loadBeanDefinitions(GenericApplicationContext context, String... locations) {
+ (new XmlBeanDefinitionReader(context)).loadBeanDefinitions(locations);
+ }
+
+ /**
+ * Creates and starts the Spring context while optionally starting any loaded Camel contexts.
+ *
+ * @param testClass the test class that is being executed
+ * @return the loaded Spring context
+ */
+ protected GenericApplicationContext createContext(Class<?> testClass, MergedContextConfiguration mergedConfig) {
+ ApplicationContext parentContext = null;
+ GenericApplicationContext routeExcludingContext = null;
+
+ if (mergedConfig != null) {
+ parentContext = mergedConfig.getParentApplicationContext();
+ }
+
+ if (testClass.isAnnotationPresent(ExcludeRoutes.class)) {
+ Class<?>[] excludedClasses = testClass.getAnnotation(ExcludeRoutes.class).value();
+
+ if (excludedClasses.length > 0) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Setting up package scanning excluded classes as ExcludeRoutes "
+ + "annotation was found. Excluding [" + StringUtils.arrayToCommaDelimitedString(excludedClasses) + "].");
+ }
+
+ if (parentContext == null) {
+ routeExcludingContext = new GenericApplicationContext();
+ } else {
+ routeExcludingContext = new GenericApplicationContext(parentContext);
+ }
+ routeExcludingContext.registerBeanDefinition("excludingResolver", new RootBeanDefinition(ExcludingPackageScanClassResolver.class));
+ routeExcludingContext.refresh();
+
+ ExcludingPackageScanClassResolver excludingResolver = routeExcludingContext.getBean("excludingResolver", ExcludingPackageScanClassResolver.class);
+ List<Class<?>> excluded = Arrays.asList(excludedClasses);
+ excludingResolver.setExcludedClasses(new HashSet<>(excluded));
+ } else {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Not enabling package scanning excluded classes as ExcludeRoutes "
+ + "annotation was found but no classes were excluded.");
+ }
+ }
+ }
+
+ GenericApplicationContext context;
+
+ if (routeExcludingContext != null) {
+ context = new GenericApplicationContext(routeExcludingContext);
+ } else {
+ if (parentContext != null) {
+ context = new GenericApplicationContext(parentContext);
+ } else {
+ context = new GenericApplicationContext();
+ }
+ }
+
+ return context;
+ }
+
+ /**
+ * Handles disabling of JMX on Camel contexts based on {@link DisableJmx}.
+ *
+ * @param context the initialized Spring context
+ * @param testClass the test class being executed
+ */
+ protected void handleDisableJmx(GenericApplicationContext context, Class<?> testClass) {
+ CamelSpringTestHelper.setOriginalJmxDisabledValue(System.getProperty(JmxSystemPropertyKeys.DISABLED));
+
+ if (testClass.isAnnotationPresent(DisableJmx.class)) {
+ if (testClass.getAnnotation(DisableJmx.class).value()) {
+ LOG.info("Disabling Camel JMX globally as DisableJmx annotation was found and disableJmx is set to true.");
+ System.setProperty(JmxSystemPropertyKeys.DISABLED, "true");
+ } else {
+ LOG.info("Enabling Camel JMX as DisableJmx annotation was found and disableJmx is set to false.");
+ System.clearProperty(JmxSystemPropertyKeys.DISABLED);
+ }
+ } else if (!testClass.isAnnotationPresent(EnableRouteCoverage.class)) {
+ LOG.info("Disabling Camel JMX globally for tests by default. Use the DisableJMX annotation to override the default setting.");
+ System.setProperty(JmxSystemPropertyKeys.DISABLED, "true");
+ } else {
+ LOG.info("Enabling Camel JMX as DisableJmx annotation was NOT found but EnableRouteCoverage annotation was found.");
+ System.clearProperty(JmxSystemPropertyKeys.DISABLED);
+ }
+ }
+
+ /**
+ * Handles disabling of JMX on Camel contexts based on {@link DisableJmx}.
+ *
+ * @param context the initialized Spring context
+ * @param testClass the test class being executed
+ */
+ private void handleRouteCoverage(GenericApplicationContext context, Class<?> testClass) throws Exception {
+ if (testClass.isAnnotationPresent(EnableRouteCoverage.class)) {
+ System.setProperty(CamelTestSupport.ROUTE_COVERAGE_ENABLED, "true");
+
+ CamelSpringTestHelper.doToSpringCamelContexts(context, new DoToSpringCamelContextsStrategy() {
+
+ @Override
+ public void execute(String contextName, SpringCamelContext camelContext) throws Exception {
+ LOG.info("Enabling RouteCoverage");
+ EventNotifier notifier = new RouteCoverageEventNotifier(testClass.getName(), s -> getTestMethod().getName());
+ camelContext.addService(notifier, true);
+ camelContext.getManagementStrategy().addEventNotifier(notifier);
+ }
+ });
+ }
+ }
+
+ /**
+ * Handles the processing of the {@link ProvidesBreakpoint} annotation on a test class. Exists here
+ * as it is needed in
+ *
+ * @param context the initialized Spring context containing the Camel context(s) to insert breakpoints into
+ * @param testClass the test class being processed
+ *
+ * @throws Exception if there is an error processing the class
+ */
+ protected void handleProvidesBreakpoint(GenericApplicationContext context, Class<?> testClass) throws Exception {
+ Collection<Method> methods = getAllMethods(testClass);
+ final List<Breakpoint> breakpoints = new LinkedList<>();
+
+ for (Method method : methods) {
+ if (AnnotationUtils.findAnnotation(method, ProvidesBreakpoint.class) != null) {
+ Class<?>[] argTypes = method.getParameterTypes();
+ if (argTypes.length != 0) {
+ throw new IllegalArgumentException("Method [" + method.getName()
+ + "] is annotated with ProvidesBreakpoint but is not a no-argument method.");
+ } else if (!Breakpoint.class.isAssignableFrom(method.getReturnType())) {
+ throw new IllegalArgumentException("Method [" + method.getName()
+ + "] is annotated with ProvidesBreakpoint but does not return a Breakpoint.");
+ } else if (!Modifier.isStatic(method.getModifiers())) {
+ throw new IllegalArgumentException("Method [" + method.getName()
+ + "] is annotated with ProvidesBreakpoint but is not static.");
+ } else if (!Modifier.isPublic(method.getModifiers())) {
+ throw new IllegalArgumentException("Method [" + method.getName()
+ + "] is annotated with ProvidesBreakpoint but is not public.");
+ }
+
+ try {
+ breakpoints.add((Breakpoint) method.invoke(null));
+ } catch (Exception e) {
+ throw new RuntimeException("Method [" + method.getName()
+ + "] threw exception during evaluation.", e);
+ }
+ }
+ }
+
+ if (breakpoints.size() != 0) {
+ CamelSpringTestHelper.doToSpringCamelContexts(context, new DoToSpringCamelContextsStrategy() {
+
+ @Override
+ public void execute(String contextName, SpringCamelContext camelContext)
+ throws Exception {
+ Debugger debugger = camelContext.getDebugger();
+ if (debugger == null) {
+ debugger = new DefaultDebugger();
+ camelContext.setDebugger(debugger);
+ }
+
+ for (Breakpoint breakpoint : breakpoints) {
+ LOG.info("Adding Breakpoint [{}] to CamelContext with name [{}].", breakpoint, contextName);
+ debugger.addBreakpoint(breakpoint);
+ }
+ }
+ });
+ }
+ }
+
+
+ /**
+ * Handles updating shutdown timeouts on Camel contexts based on {@link ShutdownTimeout}.
+ *
+ * @param context the initialized Spring context
+ * @param testClass the test class being executed
+ */
+ protected void handleShutdownTimeout(GenericApplicationContext context, Class<?> testClass) throws Exception {
+ final int shutdownTimeout;
+ final TimeUnit shutdownTimeUnit;
+ if (testClass.isAnnotationPresent(ShutdownTimeout.class)) {
+ shutdownTimeout = testClass.getAnnotation(ShutdownTimeout.class).value();
+ shutdownTimeUnit = testClass.getAnnotation(ShutdownTimeout.class).timeUnit();
+ } else {
+ shutdownTimeout = 10;
+ shutdownTimeUnit = TimeUnit.SECONDS;
+ }
+
+ CamelSpringTestHelper.doToSpringCamelContexts(context, new DoToSpringCamelContextsStrategy() {
+
+ @Override
+ public void execute(String contextName, SpringCamelContext camelContext)
+ throws Exception {
+ LOG.info("Setting shutdown timeout to [{} {}] on CamelContext with name [{}].", shutdownTimeout, shutdownTimeUnit, contextName);
+ camelContext.getShutdownStrategy().setTimeout(shutdownTimeout);
+ camelContext.getShutdownStrategy().setTimeUnit(shutdownTimeUnit);
+ }
+ });
+ }
+
+ /**
+ * Handles auto-intercepting of endpoints with mocks based on {@link MockEndpoints}.
+ *
+ * @param context the initialized Spring context
+ * @param testClass the test class being executed
+ */
+ protected void handleMockEndpoints(GenericApplicationContext context, Class<?> testClass) throws Exception {
+ if (testClass.isAnnotationPresent(MockEndpoints.class)) {
+ final String mockEndpoints = testClass.getAnnotation(MockEndpoints.class).value();
+ CamelSpringTestHelper.doToSpringCamelContexts(context, new DoToSpringCamelContextsStrategy() {
+
+ @Override
+ public void execute(String contextName, SpringCamelContext camelContext)
+ throws Exception {
+ LOG.info("Enabling auto mocking of endpoints matching pattern [{}] on CamelContext with name [{}].", mockEndpoints, contextName);
+ camelContext.adapt(ExtendedCamelContext.class).registerEndpointCallback(new InterceptSendToMockEndpointStrategy(mockEndpoints));
+ }
+ });
+ }
+ }
+
+ /**
+ * Handles auto-intercepting of endpoints with mocks based on {@link MockEndpointsAndSkip} and skipping the
+ * original endpoint.
+ *
+ * @param context the initialized Spring context
+ * @param testClass the test class being executed
+ */
+ protected void handleMockEndpointsAndSkip(GenericApplicationContext context, Class<?> testClass) throws Exception {
+ if (testClass.isAnnotationPresent(MockEndpointsAndSkip.class)) {
+ final String mockEndpoints = testClass.getAnnotation(MockEndpointsAndSkip.class).value();
+ CamelSpringTestHelper.doToSpringCamelContexts(context, new DoToSpringCamelContextsStrategy() {
+
+ @Override
+ public void execute(String contextName, SpringCamelContext camelContext)
+ throws Exception {
+ // resovle the property place holders of the mockEndpoints
+ String mockEndpointsValue = camelContext.resolvePropertyPlaceholders(mockEndpoints);
+ LOG.info("Enabling auto mocking and skipping of endpoints matching pattern [{}] on CamelContext with name [{}].", mockEndpointsValue, contextName);
+ camelContext.adapt(ExtendedCamelContext.class).registerEndpointCallback(new InterceptSendToMockEndpointStrategy(mockEndpointsValue, true));
+ }
+ });
+ }
+ }
+
+ /**
+ * Sets property overrides for the Camel {@link org.apache.camel.component.properties.PropertiesComponent}.
+ *
+ * @param context the pre-refresh Spring context
+ * @param testClass the test class being executed
+ */
+ protected void handleUseOverridePropertiesWithPropertiesComponent(ConfigurableApplicationContext context, Class<?> testClass) throws Exception {
+ Collection<Method> methods = getAllMethods(testClass);
+ final List<Properties> properties = new LinkedList<>();
+
+ for (Method method : methods) {
+ if (AnnotationUtils.findAnnotation(method, UseOverridePropertiesWithPropertiesComponent.class) != null) {
+ Class<?>[] argTypes = method.getParameterTypes();
+ if (argTypes.length > 0) {
+ throw new IllegalArgumentException("Method [" + method.getName()
+ + "] is annotated with UseOverridePropertiesWithPropertiesComponent but is not a no-argument method.");
+ } else if (!Properties.class.isAssignableFrom(method.getReturnType())) {
+ throw new IllegalArgumentException("Method [" + method.getName()
+ + "] is annotated with UseOverridePropertiesWithPropertiesComponent but does not return a java.util.Properties.");
+ } else if (!Modifier.isStatic(method.getModifiers())) {
+ throw new IllegalArgumentException("Method [" + method.getName()
+ + "] is annotated with UseOverridePropertiesWithPropertiesComponent but is not static.");
+ } else if (!Modifier.isPublic(method.getModifiers())) {
+ throw new IllegalArgumentException("Method [" + method.getName()
+ + "] is annotated with UseOverridePropertiesWithPropertiesComponent but is not public.");
+ }
+
+ try {
+ properties.add((Properties) method.invoke(null));
+ } catch (Exception e) {
+ throw new RuntimeException("Method [" + method.getName()
+ + "] threw exception during evaluation.", e);
+ }
+ }
+ }
+
+ Properties extra = new Properties();
+ for (Properties prop : properties) {
+ extra.putAll(prop);
+ }
+
+ if (!extra.isEmpty()) {
+ context.addBeanFactoryPostProcessor(beanFactory -> beanFactory.addBeanPostProcessor(new BeanPostProcessor() {
+ @Override
+ public Object postProcessAfterInitialization(Object bean, String beanName) {
+ if (bean instanceof CamelContext) {
+ CamelContext camelContext = (CamelContext) bean;
+ PropertiesComponent pc = camelContext.getPropertiesComponent(true);
+ LOG.info("Using {} properties to override any existing properties on the PropertiesComponent on CamelContext with name [{}].", extra.size(), camelContext.getName());
+ pc.setOverrideProperties(extra);
+ }
+ return bean;
+ }
+ }));
+ }
+ }
+
+ /**
+ * Handles starting of Camel contexts based on {@link UseAdviceWith} and other state in the JVM.
+ *
+ * @param context the initialized Spring context
+ * @param testClass the test class being executed
+ */
+ protected void handleCamelContextStartup(GenericApplicationContext context, Class<?> testClass) throws Exception {
+ boolean skip = "true".equalsIgnoreCase(System.getProperty("skipStartingCamelContext"));
+ if (skip) {
+ LOG.info("Skipping starting CamelContext(s) as system property skipStartingCamelContext is set to be true.");
+ } else if (testClass.isAnnotationPresent(UseAdviceWith.class)) {
+ if (testClass.getAnnotation(UseAdviceWith.class).value()) {
+ LOG.info("Skipping starting CamelContext(s) as UseAdviceWith annotation was found and isUseAdviceWith is set to true.");
+ skip = true;
+ } else {
+ LOG.info("Starting CamelContext(s) as UseAdviceWith annotation was found, but isUseAdviceWith is set to false.");
+ skip = false;
+ }
+ }
+
+ if (!skip) {
+ CamelSpringTestHelper.doToSpringCamelContexts(context, new DoToSpringCamelContextsStrategy() {
+
+ @Override
+ public void execute(String contextName,
+ SpringCamelContext camelContext) throws Exception {
+ LOG.info("Starting CamelContext with name [{}].", contextName);
+ camelContext.start();
+ }
+ });
+ }
+ }
+
+ /**
+ * Returns the class under test in order to enable inspection of annotations while the
+ * Spring context is being created.
+ *
+ * @return the test class that is being executed
+ * @see CamelSpringTestHelper
+ */
+ protected Class<?> getTestClass() {
+ return CamelSpringTestHelper.getTestClass();
+ }
+
+ /**
+ * Returns the test method under test.
+ *
+ * @return the method that is being executed
+ * @see CamelSpringTestHelper
+ */
+ protected Method getTestMethod() {
+ return CamelSpringTestHelper.getTestMethod();
+ }
+}
diff --git a/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/CamelSpringTestContextLoaderTestExecutionListener.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/CamelSpringTestContextLoaderTestExecutionListener.java
new file mode 100644
index 0000000..f22d5b5
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/CamelSpringTestContextLoaderTestExecutionListener.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.spring.junit5;
+
+import org.springframework.core.Ordered;
+import org.springframework.test.context.TestContext;
+import org.springframework.test.context.support.AbstractTestExecutionListener;
+
+/**
+ * Helper for {@link CamelSpringTestContextLoader} that sets the test class state
+ * in {@link CamelSpringTestHelper} almost immediately before the loader initializes
+ * the Spring context.
+ * <p/>
+ * Implemented as a listener as the state can be set on a {@code ThreadLocal} and we are pretty sure
+ * that the same thread will be used to initialize the Spring context.
+ */
+public class CamelSpringTestContextLoaderTestExecutionListener extends AbstractTestExecutionListener {
+
+ /**
+ * The default implementation returns {@link org.springframework.core.Ordered#LOWEST_PRECEDENCE},
+ * thereby ensuring that custom listeners are ordered after default
+ * listeners supplied by the framework. Can be overridden by subclasses
+ * as necessary.
+ */
+ @Override
+ public int getOrder() {
+ //set Camel first
+ return Ordered.HIGHEST_PRECEDENCE;
+ }
+
+ @Override
+ public void prepareTestInstance(TestContext testContext) throws Exception {
+ CamelSpringTestHelper.setTestClass(testContext.getTestClass());
+ CamelSpringTestHelper.setTestContext(testContext);
+ }
+}
diff --git a/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/CamelSpringTestHelper.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/CamelSpringTestHelper.java
new file mode 100644
index 0000000..1c8e91a
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/CamelSpringTestHelper.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.spring.junit5;
+
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.apache.camel.spring.SpringCamelContext;
+
+import org.springframework.context.ApplicationContext;
+import org.springframework.test.context.TestContext;
+
+/**
+ * Helper that provides state information across the levels of Spring Test that do not expose the
+ * necessary context/state for integration of Camel testing features into Spring test. Also
+ * provides utility methods.
+ * <p/>
+ * Note that this class makes use of {@link ThreadLocal}s to maintain some state. It is imperative
+ * that the state setters and getters are accessed within the scope of a single thread in order
+ * for this class to work right.
+ */
+public final class CamelSpringTestHelper {
+
+ private static ThreadLocal<String> originalJmxDisabledValue = new ThreadLocal<>();
+ private static ThreadLocal<Class<?>> testClazz = new ThreadLocal<>();
+ private static ThreadLocal<TestContext> testContext = new ThreadLocal<>();
+
+ private CamelSpringTestHelper() {
+ }
+
+ public static String getOriginalJmxDisabled() {
+ return originalJmxDisabledValue.get();
+ }
+
+ public static void setOriginalJmxDisabledValue(String originalValue) {
+ originalJmxDisabledValue.set(originalValue);
+ }
+
+ public static Class<?> getTestClass() {
+ return testClazz.get();
+ }
+
+ public static void setTestClass(Class<?> testClass) {
+ testClazz.set(testClass);
+ }
+
+ public static Method getTestMethod() {
+ return testContext.get().getTestMethod();
+ }
+
+ public static void setTestContext(TestContext context) {
+ testContext.set(context);
+ }
+
+ /**
+ * Returns all methods defined in {@code clazz} and its superclasses/interfaces.
+ */
+ public static Collection<Method> getAllMethods(Class<?> clazz) {
+ Set<Method> methods = new LinkedHashSet<>();
+ Class<?> currentClass = clazz;
+
+ while (currentClass != null) {
+ methods.addAll(Arrays.asList(clazz.getMethods()));
+ currentClass = currentClass.getSuperclass();
+ }
+
+ return methods;
+ }
+
+ /**
+ * Executes {@code strategy} against all {@link SpringCamelContext}s found in the Spring context.
+ * This method reduces the amount of repeated find and loop code throughout this class.
+ *
+ * @param context the Spring context to search
+ * @param strategy the strategy to execute against the found {@link SpringCamelContext}s
+ *
+ * @throws Exception if there is an error executing any of the strategies
+ */
+ public static void doToSpringCamelContexts(ApplicationContext context, DoToSpringCamelContextsStrategy strategy) throws Exception {
+ Map<String, SpringCamelContext> contexts = context.getBeansOfType(SpringCamelContext.class);
+
+ for (Entry<String, SpringCamelContext> entry : contexts.entrySet()) {
+ strategy.execute(entry.getKey(), entry.getValue());
+ }
+ }
+
+ public interface DoToSpringCamelContextsStrategy {
+ void execute(String contextName, SpringCamelContext camelContext) throws Exception;
+ }
+}
diff --git a/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/CamelSpringTestSupport.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/CamelSpringTestSupport.java
new file mode 100644
index 0000000..2b1c531
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/CamelSpringTestSupport.java
@@ -0,0 +1,218 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.spring.junit5;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.spring.SpringCamelContext;
+import org.apache.camel.test.ExcludingPackageScanClassResolver;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.apache.camel.util.IOHelper;
+import org.apache.camel.util.ObjectHelper;
+import org.junit.jupiter.api.AfterEach;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.support.RootBeanDefinition;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.AbstractApplicationContext;
+import org.springframework.context.support.GenericApplicationContext;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.fail;
+
+/**
+ * Base test-class for classic Spring application such as standalone, web applications.
+ * Do <tt>not</tt> use this class for Spring Boot testing, instead use <code>@RunWith(CamelSpringBootRunner.class)</code>.
+ */
+public abstract class CamelSpringTestSupport extends CamelTestSupport {
+
+ protected static ThreadLocal<AbstractApplicationContext> threadAppContext = new ThreadLocal<>();
+ protected static Object lock = new Object();
+
+ private static final Logger LOG = LoggerFactory.getLogger(CamelSpringTestSupport.class);
+
+ protected AbstractApplicationContext applicationContext;
+ protected abstract AbstractApplicationContext createApplicationContext();
+
+ @Override
+ public void postProcessTest() throws Exception {
+ if (isCreateCamelContextPerClass()) {
+ applicationContext = threadAppContext.get();
+ }
+ super.postProcessTest();
+ }
+
+ @Override
+ public void doPreSetup() throws Exception {
+ if (!"true".equalsIgnoreCase(System.getProperty("skipStartingCamelContext"))) {
+ // tell camel-spring it should not trigger starting CamelContext, since we do that later
+ // after we are finished setting up the unit test
+ synchronized (lock) {
+ SpringCamelContext.setNoStart(true);
+ if (isCreateCamelContextPerClass()) {
+ applicationContext = threadAppContext.get();
+ if (applicationContext == null) {
+ applicationContext = doCreateApplicationContext();
+ threadAppContext.set(applicationContext);
+ }
+ } else {
+ applicationContext = doCreateApplicationContext();
+ }
+ SpringCamelContext.setNoStart(false);
+ }
+ } else {
+ LOG.info("Skipping starting CamelContext as system property skipStartingCamelContext is set to be true.");
+ }
+ }
+
+ private AbstractApplicationContext doCreateApplicationContext() {
+ AbstractApplicationContext context = createApplicationContext();
+ assertNotNull(context, "Should have created a valid Spring application context");
+
+ String[] profiles = activeProfiles();
+ if (profiles != null && profiles.length > 0) {
+ // the context must not be active
+ if (context.isActive()) {
+ throw new IllegalStateException("Cannot active profiles: " + Arrays.asList(profiles) + " on active Spring application context: " + context
+ + ". The code in your createApplicationContext() method should be adjusted to create the application context with refresh = false as parameter");
+ }
+ LOG.info("Spring activating profiles: {}", Arrays.asList(profiles));
+ context.getEnvironment().setActiveProfiles(profiles);
+ }
+
+ // ensure the context has been refreshed at least once
+ if (!context.isActive()) {
+ context.refresh();
+ }
+
+ return context;
+ }
+
+ @Override
+ @AfterEach
+ public void tearDown() throws Exception {
+ super.tearDown();
+
+ if (!isCreateCamelContextPerClass()) {
+ IOHelper.close(applicationContext);
+ applicationContext = null;
+ }
+ }
+
+ @Override
+ public void doPostTearDown() throws Exception {
+ super.doPostTearDown();
+
+ if (threadAppContext.get() != null) {
+ IOHelper.close(threadAppContext.get());
+ threadAppContext.remove();
+ }
+ }
+
+ /**
+ * Create a parent context that initializes a
+ * {@link org.apache.camel.spi.PackageScanClassResolver} to exclude a set of given classes from
+ * being resolved. Typically this is used at test time to exclude certain routes,
+ * which might otherwise be just noisy, from being discovered and initialized.
+ * <p/>
+ * To use this filtering mechanism it is necessary to provide the
+ * {@link org.springframework.context.ApplicationContext} returned from here as the parent context to
+ * your test context e.g.
+ *
+ * <pre>
+ * protected AbstractXmlApplicationContext createApplicationContext() {
+ * return new ClassPathXmlApplicationContext(new String[] {"test-context.xml"}, getRouteExcludingApplicationContext());
+ * }
+ * </pre>
+ *
+ * This will, in turn, call the template methods <code>excludedRoutes</code>
+ * and <code>excludedRoute</code> to determine the classes to be excluded from scanning.
+ *
+ * @return ApplicationContext a parent {@link org.springframework.context.ApplicationContext} configured
+ * to exclude certain classes from package scanning
+ */
+ protected ApplicationContext getRouteExcludingApplicationContext() {
+ GenericApplicationContext routeExcludingContext = new GenericApplicationContext();
+ routeExcludingContext.registerBeanDefinition("excludingResolver", new RootBeanDefinition(ExcludingPackageScanClassResolver.class));
+ routeExcludingContext.refresh();
+
+ ExcludingPackageScanClassResolver excludingResolver = routeExcludingContext.getBean("excludingResolver", ExcludingPackageScanClassResolver.class);
+ List<Class<?>> excluded = Arrays.asList(excludeRoutes());
+ excludingResolver.setExcludedClasses(new HashSet<>(excluded));
+
+ return routeExcludingContext;
+ }
+
+ /**
+ * Template method used to exclude {@link org.apache.camel.Route} from the test time context
+ * route scanning
+ *
+ * @return Class[] the classes to be excluded from test time context route scanning
+ */
+ protected Class<?>[] excludeRoutes() {
+ Class<?> excludedRoute = excludeRoute();
+ return excludedRoute != null ? new Class[] {excludedRoute} : new Class[0];
+ }
+
+ /**
+ * Template method used to exclude a {@link org.apache.camel.Route} from the test camel context
+ */
+ protected Class<?> excludeRoute() {
+ return null;
+ }
+
+ /**
+ * Looks up the mandatory spring bean of the given name and type, failing if
+ * it is not present or the correct type
+ */
+ public <T> T getMandatoryBean(Class<T> type, String name) {
+ Object value = applicationContext.getBean(name);
+ assertNotNull(value, "No spring bean found for name <" + name + ">");
+ if (type.isInstance(value)) {
+ return type.cast(value);
+ } else {
+ fail("Spring bean <" + name + "> is not an instanceof " + type.getName() + " but is of type " + ObjectHelper.className(value));
+ return null;
+ }
+ }
+
+ /**
+ * Which active profiles should be used.
+ * <p/>
+ * <b>Important:</b> When using active profiles, then the code in {@link #createApplicationContext()} should create
+ * the Spring {@link org.springframework.context.support.AbstractApplicationContext} without refreshing. For example creating an
+ * {@link org.springframework.context.support.ClassPathXmlApplicationContext} you would need to pass in
+ * <tt>false</tt> in the refresh parameter, in the constructor.
+ * Camel will thrown an {@link IllegalStateException} if this is not correct stating this problem.
+ * The reason is that we cannot active profiles <b>after</b> a Spring application context has already
+ * been refreshed, and is active.
+ *
+ * @return an array of active profiles to use, use <tt>null</tt> to not use any active profiles.
+ */
+ protected String[] activeProfiles() {
+ return null;
+ }
+
+ @Override
+ protected CamelContext createCamelContext() throws Exception {
+ // don't start the springCamelContext if we
+ return SpringCamelContext.springCamelContext(applicationContext, false);
+ }
+}
diff --git a/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/CamelTestContextBootstrapper.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/CamelTestContextBootstrapper.java
new file mode 100644
index 0000000..6120d02
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/CamelTestContextBootstrapper.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.spring.junit5;
+
+import org.springframework.test.context.ContextLoader;
+import org.springframework.test.context.support.DefaultTestContextBootstrapper;
+
+/**
+ * To bootstrap Camel for testing with Spring 4.1 onwards.
+ */
+public class CamelTestContextBootstrapper extends DefaultTestContextBootstrapper {
+
+ @Override
+ protected Class<? extends ContextLoader> getDefaultContextLoaderClass(Class<?> testClass) {
+ return CamelSpringTestContextLoader.class;
+ }
+}
diff --git a/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/DisableJmx.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/DisableJmx.java
new file mode 100644
index 0000000..2289569
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/DisableJmx.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.spring.junit5;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Indicates if JMX should be globally disabled in the {@code CamelContext}s that are bootstrapped
+ * during the test through the use of Spring Test loaded application contexts. Note that the
+ * presence of this annotation will result in the manipulation of System Properties that
+ * will affect Camel contexts constructed outside of the Spring Test loaded application contexts.
+ */
+@Documented
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE})
+public @interface DisableJmx {
+
+ /**
+ * Whether the test annotated with this annotation should be run with JMX disabled in Camel.
+ * Defaults to {@code true}.
+ */
+ boolean value() default true;
+}
diff --git a/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/DisableJmxTestExecutionListener.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/DisableJmxTestExecutionListener.java
new file mode 100644
index 0000000..6cc9761
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/DisableJmxTestExecutionListener.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.spring.junit5;
+
+import org.apache.camel.api.management.JmxSystemPropertyKeys;
+import org.springframework.test.context.TestContext;
+import org.springframework.test.context.support.AbstractTestExecutionListener;
+
+/**
+ * Provides reset to pre-test state behavior for global enable/disable of JMX
+ * support in Camel through the use of {@link DisableJmx}.
+ * Tries to ensure that the pre-test value is restored.
+ */
+public class DisableJmxTestExecutionListener extends AbstractTestExecutionListener {
+
+ @Override
+ public void afterTestClass(TestContext testContext) throws Exception {
+ if (CamelSpringTestHelper.getOriginalJmxDisabled() == null) {
+ System.clearProperty(JmxSystemPropertyKeys.DISABLED);
+ } else {
+ System.setProperty(JmxSystemPropertyKeys.DISABLED, CamelSpringTestHelper.getOriginalJmxDisabled());
+ }
+ }
+
+}
diff --git a/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/EnableRouteCoverage.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/EnableRouteCoverage.java
new file mode 100644
index 0000000..4b3c7db
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/EnableRouteCoverage.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.spring.junit5;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Enables dumping route coverage statistic.
+ * The route coverage status is written as xml files in the <tt>target/camel-route-coverage</tt> directory after the test has finished.
+ * <p/>
+ * This allows tooling or manual inspection of the stats, so you can generate a route trace diagram of which EIPs
+ * have been in use and which have not. Similar concepts as a code coverage report.
+ * <p/>
+ * You can also turn on route coverage globally via setting JVM system property <tt>CamelTestRouteCoverage=true</tt>.
+ */
+@Documented
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE})
+public @interface EnableRouteCoverage {
+
+}
diff --git a/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/ExcludeRoutes.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/ExcludeRoutes.java
new file mode 100644
index 0000000..c0e0ddb
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/ExcludeRoutes.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.spring.junit5;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.apache.camel.RoutesBuilder;
+
+/**
+ * Indicates if certain route builder classes should be excluded from discovery.
+ * Initializes a {@link org.apache.camel.spi.PackageScanClassResolver} to exclude a set of given
+ * classes from being resolved. Typically this is used at test time to exclude certain routes,
+ * which might otherwise be noisy, from being discovered and initialized.
+ */
+@Documented
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE})
+public @interface ExcludeRoutes {
+
+ /**
+ * The classes to exclude from resolution when using package scanning.
+ */
+ Class<? extends RoutesBuilder>[] value() default {};
+}
diff --git a/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/MockEndpoints.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/MockEndpoints.java
new file mode 100644
index 0000000..0a0da64
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/MockEndpoints.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.spring.junit5;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.apache.camel.impl.engine.InterceptSendToMockEndpointStrategy;
+
+/**
+ * Triggers the auto-mocking of endpoints whose URIs match the provided filter. The default
+ * filter is "*" which matches all endpoints. See {@link InterceptSendToMockEndpointStrategy} for
+ * more details on the registration of the mock endpoints.
+ */
+@Documented
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE})
+public @interface MockEndpoints {
+
+ /**
+ * The pattern to use for matching endpoints to enable mocking on.
+ */
+ String value() default "*";
+}
diff --git a/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/MockEndpointsAndSkip.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/MockEndpointsAndSkip.java
new file mode 100644
index 0000000..bad37b7
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/MockEndpointsAndSkip.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.spring.junit5;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.apache.camel.impl.engine.InterceptSendToMockEndpointStrategy;
+
+/**
+ * Triggers the auto-mocking of endpoints whose URIs match the provided filter with the added provision
+ * that the endpoints are also skipped. The default filter is "*" which matches all endpoints.
+ * See {@link InterceptSendToMockEndpointStrategy} for more details on the registration of the mock endpoints.
+ */
+@Documented
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE})
+public @interface MockEndpointsAndSkip {
+
+ /**
+ * The pattern to use for matching endpoints to enable mocking on.
+ */
+ String value() default "*";
+}
diff --git a/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/ProvidesBreakpoint.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/ProvidesBreakpoint.java
new file mode 100644
index 0000000..e5620dc
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/ProvidesBreakpoint.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.spring.junit5;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.apache.camel.spi.Breakpoint;
+
+/**
+ * Indicates that the annotated method returns a {@link 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 {@code public}, {@code static}, take no arguments, and return {@link Breakpoint}.
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD})
+public @interface ProvidesBreakpoint {
+}
diff --git a/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/RouteCoverageDumper.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/RouteCoverageDumper.java
new file mode 100644
index 0000000..34816ef
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/RouteCoverageDumper.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.spring.junit5;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.api.management.ManagedCamelContext;
+import org.apache.camel.api.management.mbean.ManagedCamelContextMBean;
+import org.apache.camel.util.IOHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Helper to dump route coverage when using {@link EnableRouteCoverage}.
+ */
+public final class RouteCoverageDumper {
+
+ private static final Logger LOG = LoggerFactory.getLogger(RouteCoverageDumper.class);
+
+ private RouteCoverageDumper() {
+ }
+
+ public static void dumpRouteCoverage(CamelContext context, String testClassName, String testName) {
+ try {
+ String dir = "target/camel-route-coverage";
+ String name = testClassName + "-" + testName + ".xml";
+
+ ManagedCamelContextMBean managedCamelContext = context.getExtension(ManagedCamelContext.class).getManagedCamelContext();
+ if (managedCamelContext == null) {
+ LOG.warn("Cannot dump route coverage to file as JMX is not enabled. Override useJmx() method to enable JMX in the unit test classes.");
+ } else {
+ String xml = managedCamelContext.dumpRoutesCoverageAsXml();
+ String combined = "<camelRouteCoverage>\n" + gatherTestDetailsAsXml(testClassName, testName) + xml + "\n</camelRouteCoverage>";
+
+ File file = new File(dir);
+ // ensure dir exists
+ file.mkdirs();
+ file = new File(dir, name);
+
+ LOG.info("Dumping route coverage to file: " + file);
+ InputStream is = new ByteArrayInputStream(combined.getBytes());
+ OutputStream os = new FileOutputStream(file, false);
+ IOHelper.copyAndCloseInput(is, os);
+ IOHelper.close(os);
+ }
+ } catch (Exception e) {
+ LOG.warn("Error during dumping route coverage statistic. This exception is ignored.", e);
+ }
+
+ }
+
+ /**
+ * Gathers test details as xml
+ */
+ private static String gatherTestDetailsAsXml(String testClassName, String testName) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("<test>\n");
+ sb.append(" <class>").append(testClassName).append("</class>\n");
+ sb.append(" <method>").append(testName).append("</method>\n");
+ sb.append("</test>\n");
+ return sb.toString();
+ }
+}
diff --git a/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/RouteCoverageEventNotifier.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/RouteCoverageEventNotifier.java
new file mode 100644
index 0000000..3642323
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/RouteCoverageEventNotifier.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.spring.junit5;
+
+import java.util.function.Function;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.spi.CamelEvent;
+import org.apache.camel.spi.CamelEvent.CamelContextStoppingEvent;
+import org.apache.camel.support.EventNotifierSupport;
+
+public class RouteCoverageEventNotifier extends EventNotifierSupport {
+
+ private final String testClassName;
+ private final Function testMethodName;
+
+ public RouteCoverageEventNotifier(String testClassName, Function testMethodName) {
+ this.testClassName = testClassName;
+ this.testMethodName = testMethodName;
+ setIgnoreCamelContextEvents(false);
+ setIgnoreExchangeEvents(true);
+ }
+
+ @Override
+ public boolean isEnabled(CamelEvent event) {
+ return event instanceof CamelContextStoppingEvent;
+ }
+
+ @Override
+ public void notify(CamelEvent event) throws Exception {
+ CamelContext context = ((CamelContextStoppingEvent) event).getContext();
+ String testName = (String) testMethodName.apply(this);
+ RouteCoverageDumper.dumpRouteCoverage(context, testClassName, testName);
+ }
+
+}
diff --git a/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/ShutdownTimeout.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/ShutdownTimeout.java
new file mode 100644
index 0000000..a8c8efd
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/ShutdownTimeout.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.spring.junit5;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Indicates to set the shutdown timeout of all {@code CamelContext}s instantiated through the
+ * use of Spring Test loaded application contexts. If no annotation is used, the timeout is
+ * automatically reduced to 10 seconds by the test framework. If the annotation is present the
+ * shutdown timeout is set based on the value of {@link #value()}.
+ */
+@Documented
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE})
+public @interface ShutdownTimeout {
+
+ /**
+ * The shutdown timeout to set on the {@code CamelContext}(s).
+ * Defaults to {@code 10} seconds.
+ */
+ int value() default 10;
+
+ /**
+ * The time unit that {@link #value()} is in.
+ */
+ TimeUnit timeUnit() default TimeUnit.SECONDS;
+}
diff --git a/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/StopWatchTestExecutionListener.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/StopWatchTestExecutionListener.java
new file mode 100644
index 0000000..8b6627b
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/StopWatchTestExecutionListener.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.spring.junit5;
+
+import org.apache.camel.util.StopWatch;
+import org.apache.camel.util.TimeUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.test.context.TestContext;
+import org.springframework.test.context.support.AbstractTestExecutionListener;
+
+/**
+ * An execution listener that simulates the timing output built in to {@link org.apache.camel.test.junit5.CamelTestSupport}.
+ */
+public class StopWatchTestExecutionListener extends AbstractTestExecutionListener {
+
+ protected static ThreadLocal<StopWatch> threadStopWatch = new ThreadLocal<>();
+
+ /**
+ * Exists primarily for testing purposes, but allows for access to the underlying stop watch instance for a test.
+ */
+ public static StopWatch getStopWatch() {
+ return threadStopWatch.get();
+ }
+
+ @Override
+ public void beforeTestMethod(TestContext testContext) throws Exception {
+ StopWatch stopWatch = new StopWatch();
+ threadStopWatch.set(stopWatch);
+ }
+
+ @Override
+ public void afterTestMethod(TestContext testContext) throws Exception {
+ StopWatch watch = threadStopWatch.get();
+ if (watch != null) {
+ long time = watch.taken();
+ Logger log = LoggerFactory.getLogger(testContext.getTestClass());
+
+ log.info("********************************************************************************");
+ log.info("Testing done: " + testContext.getTestMethod().getName() + "(" + testContext.getTestClass().getName() + ")");
+ log.info("Took: " + TimeUtils.printDuration(time) + " (" + time + " millis)");
+ log.info("********************************************************************************");
+
+ threadStopWatch.remove();
+ }
+ }
+
+}
diff --git a/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/UseAdviceWith.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/UseAdviceWith.java
new file mode 100644
index 0000000..a5e0dab
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/UseAdviceWith.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.spring.junit5;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.apache.camel.CamelContext;
+
+/**
+ * Indicates the use of {@code adviceWith()} within the test class. If a class is annotated with
+ * this annotation and {@link UseAdviceWith#value()} returns true, any
+ * {@code CamelContext}s bootstrapped during the test through the use of Spring Test loaded
+ * application contexts will not be started automatically. The test author is responsible for
+ * injecting the Camel contexts into the test and executing {@link CamelContext#start()} on them
+ * at the appropriate time after any advice has been applied to the routes in the Camel context(s).
+ */
+@Documented
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE})
+public @interface UseAdviceWith {
+
+ /**
+ * Whether the test annotated with this annotation should be treated as if
+ * {@code adviceWith()} is in use in the test and the Camel contexts should not be started
+ * automatically.
+ * Defaults to {@code true}.
+ */
+ boolean value() default true;
+}
diff --git a/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/UseOverridePropertiesWithPropertiesComponent.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/UseOverridePropertiesWithPropertiesComponent.java
new file mode 100644
index 0000000..8dff150
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/UseOverridePropertiesWithPropertiesComponent.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.spring.junit5;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Indicates that the annotated method returns a {@link java.util.Properties} for use in the test, and that
+ * those properties override any existing properties configured on the {@link org.apache.camel.component.properties.PropertiesComponent}.
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD})
+public @interface UseOverridePropertiesWithPropertiesComponent {
+
+}
diff --git a/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/issues/AdviceWithInterceptSendToEndpointWithLoadbalancerTest.java b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/issues/AdviceWithInterceptSendToEndpointWithLoadbalancerTest.java
new file mode 100644
index 0000000..37c6772
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/issues/AdviceWithInterceptSendToEndpointWithLoadbalancerTest.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.issues;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.model.RouteDefinition;
+import org.apache.camel.reifier.RouteReifier;
+import org.apache.camel.test.spring.junit5.CamelSpringTestSupport;
+import org.junit.jupiter.api.Test;
+import org.springframework.context.support.AbstractApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+public class AdviceWithInterceptSendToEndpointWithLoadbalancerTest extends CamelSpringTestSupport {
+
+ @Override
+ protected AbstractApplicationContext createApplicationContext() {
+ return new ClassPathXmlApplicationContext("org/apache/camel/test/issues/AdviceWithInterceptSendToEndpointWithLoadbalancerTest.xml");
+ }
+
+ @Override
+ public boolean isUseAdviceWith() {
+ return true;
+ }
+
+ @Test
+ public void testSimpleMultipleAdvice() throws Exception {
+ RouteDefinition route = context.getRouteDefinitions().get(0);
+ RouteReifier.adviceWith(route, context, new RouteBuilder() {
+ public void configure() throws Exception {
+ interceptSendToEndpoint("seda:end1")
+ .skipSendToOriginalEndpoint()
+ .to("mock:end");
+ }
+ });
+
+ context.start();
+
+ getMockEndpoint("mock:end").expectedMessageCount(1);
+
+ template.sendBody("direct:start", "Hello World");
+
+ assertMockEndpointsSatisfied();
+ }
+
+ public static class LoadbalancerTestRoute extends RouteBuilder {
+
+ @Override
+ public void configure() throws Exception {
+ from("direct:start")
+ .loadBalance().failover()
+ .to("seda:end1", "seda:end2");
+ }
+ }
+}
\ No newline at end of file
diff --git a/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/issues/AdviceWithOnCompletionTest.java b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/issues/AdviceWithOnCompletionTest.java
new file mode 100644
index 0000000..0c44cb7
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/issues/AdviceWithOnCompletionTest.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.issues;
+
+import org.apache.camel.builder.AdviceWithRouteBuilder;
+import org.apache.camel.model.RouteDefinition;
+import org.apache.camel.reifier.RouteReifier;
+import org.apache.camel.test.spring.junit5.CamelSpringTestSupport;
+import org.junit.jupiter.api.Test;
+import org.springframework.context.support.AbstractApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+public class AdviceWithOnCompletionTest extends CamelSpringTestSupport {
+
+ @Override
+ protected AbstractApplicationContext createApplicationContext() {
+ return new ClassPathXmlApplicationContext("org/apache/camel/test/issues/AdviceWithOnCompletionTest.xml");
+ }
+
+ @Override
+ public boolean isUseAdviceWith() {
+ return true;
+ }
+
+ @Test
+ public void testOnCompletion() throws Exception {
+ RouteDefinition route = context.getRouteDefinitions().get(0);
+ RouteReifier.adviceWith(route, context, new AdviceWithRouteBuilder() {
+ public void configure() throws Exception {
+ replaceFromWith("direct:start");
+
+ weaveAddFirst().convertBodyTo(String.class);
+ weaveAddLast().to("mock:result");
+ }
+ });
+
+ context.start();
+
+ getMockEndpoint("mock:result").expectedMessageCount(1);
+ getMockEndpoint("mock:result").message(0).body().isInstanceOf(String.class);
+
+ template.sendBody("direct:start", "Hello World".getBytes());
+
+ assertMockEndpointsSatisfied();
+ }
+
+}
\ No newline at end of file
diff --git a/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/issues/AdviceWithOnExceptionMultipleIssueTest.java b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/issues/AdviceWithOnExceptionMultipleIssueTest.java
new file mode 100644
index 0000000..c2d1437
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/issues/AdviceWithOnExceptionMultipleIssueTest.java
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.issues;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.AdviceWithRouteBuilder;
+import org.apache.camel.reifier.RouteReifier;
+import org.apache.camel.test.spring.junit5.CamelSpringTestSupport;
+import org.junit.jupiter.api.Test;
+import org.springframework.context.support.AbstractApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+public class AdviceWithOnExceptionMultipleIssueTest extends CamelSpringTestSupport {
+
+ @Override
+ protected AbstractApplicationContext createApplicationContext() {
+ return new ClassPathXmlApplicationContext("org/apache/camel/test/issues/AdviceWithOnExceptionMultipleIssueTest.xml");
+ }
+
+ @Override
+ public boolean isUseAdviceWith() {
+ return true;
+ }
+
+ @Test
+ public void testSimpleMultipleAdvice() throws Exception {
+ RouteReifier.adviceWith(context.getRouteDefinition("RouteA"), context, new AdviceWithRouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ interceptSendToEndpoint("mock:resultA").process(new Processor() {
+ @Override
+ public void process(Exchange exchange) throws Exception {
+ }
+ });
+ }
+ });
+
+ RouteReifier.adviceWith(context.getRouteDefinition("RouteB"), context, new AdviceWithRouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ }
+ });
+
+ context.start();
+
+ getMockEndpoint("mock:resultA").expectedMessageCount(1);
+ template.sendBody("direct:startA", "a trigger");
+ assertMockEndpointsSatisfied();
+ }
+
+ @Test
+ public void testMultipleAdviceWithExceptionThrown() throws Exception {
+ RouteReifier.adviceWith(context.getRouteDefinition("RouteA"), context, new AdviceWithRouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ interceptSendToEndpoint("mock:resultA").process(new Processor() {
+ @Override
+ public void process(Exchange exchange) throws Exception {
+ throw new Exception("my exception");
+ }
+ });
+ }
+ });
+
+ context.start();
+
+ getMockEndpoint("mock:resultA").expectedMessageCount(0);
+ template.sendBody("direct:startA", "a trigger");
+ assertMockEndpointsSatisfied();
+ }
+
+ @Test
+ public void testMultipleAdvice() throws Exception {
+ RouteReifier.adviceWith(context.getRouteDefinition("RouteA"), context, new AdviceWithRouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ interceptSendToEndpoint("mock:resultA").process(new Processor() {
+ @Override
+ public void process(Exchange exchange) throws Exception {
+ throw new Exception("my exception");
+ }
+ });
+ }
+ });
+
+ RouteReifier.adviceWith(context.getRouteDefinition("RouteB"), context, new AdviceWithRouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ }
+ });
+
+ context.start();
+
+ getMockEndpoint("mock:resultA").expectedMessageCount(0);
+ template.sendBody("direct:startA", "a trigger");
+ assertMockEndpointsSatisfied();
+ }
+
+}
diff --git a/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/issues/MockEndpointsAndSkipTest.java b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/issues/MockEndpointsAndSkipTest.java
new file mode 100644
index 0000000..910080c
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/issues/MockEndpointsAndSkipTest.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.issues;
+
+import org.apache.camel.test.spring.junit5.CamelSpringTestSupport;
+import org.junit.jupiter.api.Test;
+import org.springframework.context.support.AbstractApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+public class MockEndpointsAndSkipTest extends CamelSpringTestSupport {
+
+ @Override
+ protected AbstractApplicationContext createApplicationContext() {
+ return new ClassPathXmlApplicationContext("org/apache/camel/test/issues/MockEndpointsAndSkipTest.xml");
+ }
+
+ @Override
+ public String isMockEndpointsAndSkip() {
+ return "seda*";
+ }
+
+ @Test
+ public void testHelloWorld() throws Exception {
+ getMockEndpoint("mock:seda:foo").expectedBodiesReceived("Hello World");
+
+ template.sendBody("direct:start", "Hello World");
+
+ assertMockEndpointsSatisfied();
+ }
+
+
+}
diff --git a/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/patterns/DebugSpringCamelContextTest.java b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/patterns/DebugSpringCamelContextTest.java
new file mode 100644
index 0000000..3be8b2e
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/patterns/DebugSpringCamelContextTest.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.patterns;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.springframework.context.support.AbstractApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+
+public class DebugSpringCamelContextTest extends DebugSpringTest {
+
+ @Override
+ protected RouteBuilder createRouteBuilder() {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ // there is no route to be used
+ }
+ };
+ }
+
+ @Override
+ protected AbstractApplicationContext createApplicationContext() {
+ return new ClassPathXmlApplicationContext("org/apache/camel/test/patterns/applicationContext.xml");
+ }
+}
diff --git a/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/patterns/DebugSpringTest.java b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/patterns/DebugSpringTest.java
new file mode 100644
index 0000000..6dec6be
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/patterns/DebugSpringTest.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.patterns;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.model.ProcessorDefinition;
+import org.apache.camel.test.spring.junit5.CamelSpringTestSupport;
+import org.junit.jupiter.api.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.support.AbstractApplicationContext;
+import org.springframework.context.support.GenericApplicationContext;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class DebugSpringTest extends CamelSpringTestSupport {
+
+ private static final Logger LOG = LoggerFactory.getLogger(DebugSpringTest.class);
+ private boolean debugged;
+
+ @Override
+ public boolean isUseDebugger() {
+ // must enable debugger
+ return true;
+ }
+
+ @Override
+ protected void debugBefore(Exchange exchange, Processor processor,
+ ProcessorDefinition<?> definition, String id, String shortName) {
+ // this method is invoked before we are about to enter the given processor
+ // from your Java editor you can just add a breakpoint in the code line below
+ LOG.info("Before " + definition + " with body " + exchange.getIn().getBody());
+ debugged = true;
+ }
+
+
+ @Test
+ public void testDebugger() throws Exception {
+ // set mock expectations
+ getMockEndpoint("mock:a").expectedMessageCount(1);
+ getMockEndpoint("mock:b").expectedMessageCount(1);
+
+ // send a message
+ template.sendBody("direct:start", "World");
+
+ // assert mocks
+ assertMockEndpointsSatisfied();
+ assertTrue(debugged, "The debugger is not called!");
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ // this is the route we want to debug
+ from("direct:start")
+ .to("mock:a")
+ .transform(body().prepend("Hello "))
+ .to("mock:b");
+ }
+ };
+ }
+
+
+ @Override
+ protected AbstractApplicationContext createApplicationContext() {
+ return new GenericApplicationContext();
+ }
+
+}
diff --git a/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/patterns/MyProduceBean.java b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/patterns/MyProduceBean.java
new file mode 100644
index 0000000..87cafd8
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/patterns/MyProduceBean.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.patterns;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Produce;
+import org.apache.camel.ProducerTemplate;
+
+public class MyProduceBean {
+
+ @Produce("mock:result")
+ MySender sender;
+
+ @EndpointInject("direct:start")
+ ProducerTemplate template;
+
+ public void doSomething(String body) {
+ sender.send(body);
+ }
+
+ public ProducerTemplate getProducerTemplate() {
+ return template;
+ }
+}
diff --git a/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/patterns/MySender.java b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/patterns/MySender.java
new file mode 100644
index 0000000..6bc19f5
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/patterns/MySender.java
@@ -0,0 +1,22 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.patterns;
+
+public interface MySender {
+
+ void send(String body);
+}
diff --git a/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/patterns/ProduceBeanTest.java b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/patterns/ProduceBeanTest.java
new file mode 100644
index 0000000..01597ba
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/patterns/ProduceBeanTest.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.patterns;
+
+import org.apache.camel.test.spring.junit5.CamelSpringTestSupport;
+import org.junit.jupiter.api.Test;
+import org.springframework.context.support.AbstractApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+public class ProduceBeanTest extends CamelSpringTestSupport {
+
+ @Test
+ public void testProduceBean() throws Exception {
+ getMockEndpoint("mock:result").expectedMessageCount(1);
+
+ template.sendBody("direct:start", "Hello World");
+
+ assertMockEndpointsSatisfied();
+ }
+
+ @Override
+ protected AbstractApplicationContext createApplicationContext() {
+ return new ClassPathXmlApplicationContext("org/apache/camel/test/patterns/ProduceBeanTest.xml");
+ }
+}
diff --git a/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/patterns/ProducerBeanInjectTest.java b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/patterns/ProducerBeanInjectTest.java
new file mode 100644
index 0000000..6460beb
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/patterns/ProducerBeanInjectTest.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.patterns;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.context.support.AbstractApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+public class ProducerBeanInjectTest {
+
+ @Test
+ public void checkProducerBeanInjection() {
+ AbstractApplicationContext applicationContext = createApplicationContext();
+ MyProduceBean bean = applicationContext.getBean("myProduceBean", MyProduceBean.class);
+ assertNotNull(bean.getProducerTemplate(), "The producerTemplate should not be null.");
+ assertEquals("Camel rocks!", bean.getProducerTemplate().requestBody("Camel"), "Get a wrong response");
+ }
+
+ protected AbstractApplicationContext createApplicationContext() {
+ return new ClassPathXmlApplicationContext("org/apache/camel/test/patterns/ProduceBeanInjectTest.xml");
+ }
+
+}
diff --git a/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/patterns/SimpleMockTest.java b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/patterns/SimpleMockTest.java
new file mode 100644
index 0000000..b60711d
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/patterns/SimpleMockTest.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.patterns;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Produce;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.spring.junit5.CamelSpringTestSupport;
+import org.junit.jupiter.api.Test;
+import org.springframework.context.support.AbstractApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+public class SimpleMockTest extends CamelSpringTestSupport {
+
+ @EndpointInject("mock:result")
+ protected MockEndpoint resultEndpoint;
+
+ @Produce("direct:start")
+ protected ProducerTemplate template;
+
+ @Override
+ protected AbstractApplicationContext createApplicationContext() {
+ 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();
+ }
+
+ @Test
+ public void testMockAgain() throws Exception {
+ String expectedBody = "Bye World";
+
+ resultEndpoint.expectedBodiesReceived(expectedBody);
+
+ template.sendBodyAndHeader(expectedBody, "foo", "bar");
+
+ resultEndpoint.assertIsSatisfied();
+ }
+
+}
diff --git a/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringActiveProfileTest.java b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringActiveProfileTest.java
new file mode 100644
index 0000000..10b2d6d
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringActiveProfileTest.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.spring;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Produce;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.spring.junit5.CamelSpringTest;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.ContextConfiguration;
+
+// START SNIPPET: e1
+
+/**
+ * Spring style testing with annotations to configure and setup the test.
+ * <p/>
+ * As we do next extend any base test class, we need to inject our resources
+ * for testing such as the {@link CamelContext} and {@link ProducerTemplate}.
+ */
+@ContextConfiguration
+@ActiveProfiles("test")
+@CamelSpringTest
+public class CamelSpringActiveProfileTest {
+
+ @Autowired
+ protected CamelContext camelContext;
+
+ @Produce("direct:start")
+ protected ProducerTemplate start;
+
+ @Test
+ public void testLoadActiveProfile() throws InterruptedException {
+ MockEndpoint mock = camelContext.getEndpoint("mock:test", MockEndpoint.class);
+ mock.expectedBodiesReceived("Hello World");
+ start.sendBody("World");
+ mock.assertIsSatisfied();
+ }
+
+}
+// END SNIPPET: e1
diff --git a/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringDisableJmxInheritedOverrideTest.java b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringDisableJmxInheritedOverrideTest.java
new file mode 100644
index 0000000..0412eb6
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringDisableJmxInheritedOverrideTest.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.spring;
+
+import org.apache.camel.impl.engine.DefaultManagementStrategy;
+import org.apache.camel.test.spring.junit5.DisableJmx;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+@DisableJmx
+public class CamelSpringDisableJmxInheritedOverrideTest
+ extends CamelSpringDisableJmxTest {
+
+ @Override
+ @Test
+ public void testJmx() {
+ assertEquals(DefaultManagementStrategy.class, camelContext.getManagementStrategy().getClass());
+ }
+}
diff --git a/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringDisableJmxInheritedTest.java b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringDisableJmxInheritedTest.java
new file mode 100644
index 0000000..43add89
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringDisableJmxInheritedTest.java
@@ -0,0 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.spring;
+
+public class CamelSpringDisableJmxInheritedTest
+ extends CamelSpringDisableJmxTest {
+}
diff --git a/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringDisableJmxTest.java b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringDisableJmxTest.java
new file mode 100644
index 0000000..902168a
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringDisableJmxTest.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.spring;
+
+import org.apache.camel.management.JmxManagementStrategy;
+import org.apache.camel.test.spring.junit5.DisableJmx;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+@DisableJmx(false)
+public class CamelSpringDisableJmxTest
+ extends CamelSpringPlainTest {
+
+ @Test
+ @Override
+ public void testJmx() {
+ assertEquals(JmxManagementStrategy.class, camelContext.getManagementStrategy().getClass());
+ }
+}
diff --git a/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringExcludeRoutesTest.java b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringExcludeRoutesTest.java
new file mode 100644
index 0000000..661ca03
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringExcludeRoutesTest.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.spring;
+
+import org.apache.camel.test.spring.junit5.ExcludeRoutes;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+@ExcludeRoutes(TestRouteBuilder.class)
+public class CamelSpringExcludeRoutesTest
+ extends CamelSpringPlainTest {
+
+ @Override
+ @Test
+ public void testExcludedRoute() {
+ assertNull(camelContext.getRoute("excludedRoute"));
+ }
+}
diff --git a/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringOverridePropertiesForPropertyInjectTest.java b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringOverridePropertiesForPropertyInjectTest.java
new file mode 100644
index 0000000..98aaab5
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringOverridePropertiesForPropertyInjectTest.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.spring;
+
+import java.util.Properties;
+
+import org.apache.camel.Produce;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.test.spring.junit5.CamelSpringTest;
+import org.apache.camel.test.spring.junit5.UseOverridePropertiesWithPropertiesComponent;
+import org.junit.jupiter.api.Test;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.ContextConfiguration;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
+
+@CamelSpringTest
+@ContextConfiguration
+@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
+public class CamelSpringOverridePropertiesForPropertyInjectTest {
+
+ private static final String EXPECTED_PROPERTY_VALUE = "The value is overriden";
+
+ @Produce("direct:start-override-route")
+ private ProducerTemplate start;
+
+ @UseOverridePropertiesWithPropertiesComponent
+ public static Properties override() {
+ Properties answer = new Properties();
+ answer.put("property.to.override", EXPECTED_PROPERTY_VALUE);
+ return answer;
+ }
+
+ @Test
+ public void testOverride() {
+ String response = start.requestBody((Object)"ignored", String.class);
+
+ assertThat(response, is(EXPECTED_PROPERTY_VALUE));
+ }
+
+}
diff --git a/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringOverridePropertiesTest.java b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringOverridePropertiesTest.java
new file mode 100644
index 0000000..aaed058
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringOverridePropertiesTest.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.spring;
+
+import java.util.Properties;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Produce;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.spring.junit5.CamelSpringTest;
+import org.apache.camel.test.spring.junit5.UseOverridePropertiesWithPropertiesComponent;
+import org.junit.jupiter.api.Test;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.ContextConfiguration;
+
+@CamelSpringTest
+@ContextConfiguration
+// Put here to prevent Spring context caching across tests and test methods since some tests inherit
+// from this test and therefore use the same Spring context. Also because we want to reset the
+// Camel context and mock endpoints between test methods automatically.
+@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
+public class CamelSpringOverridePropertiesTest {
+
+ @Produce("direct:start")
+ private ProducerTemplate start;
+
+ @EndpointInject("mock:a")
+ private MockEndpoint mockA;
+
+ @EndpointInject("mock:test")
+ private MockEndpoint mockTest;
+
+ @EndpointInject("mock:foo")
+ private MockEndpoint mockFoo;
+
+ @UseOverridePropertiesWithPropertiesComponent
+ public static Properties override() {
+ Properties answer = new Properties();
+ answer.put("cool.end", "mock:foo");
+ return answer;
+ }
+
+ @Test
+ public void testOverride() throws Exception {
+ mockA.expectedBodiesReceived("Camel");
+ mockTest.expectedMessageCount(0);
+ mockFoo.expectedBodiesReceived("Hello Camel");
+
+ start.sendBody("Camel");
+
+ mockA.assertIsSatisfied();
+ mockTest.assertIsSatisfied();
+ mockFoo.assertIsSatisfied();
+ }
+
+}
diff --git a/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringPlainTest.java b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringPlainTest.java
new file mode 100644
index 0000000..bed1c68
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringPlainTest.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.spring;
+
+import java.util.concurrent.TimeUnit;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Produce;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.ServiceStatus;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.impl.engine.DefaultManagementStrategy;
+import org.apache.camel.test.spring.junit5.CamelSpringTest;
+import org.apache.camel.test.spring.junit5.StopWatchTestExecutionListener;
+import org.apache.camel.util.StopWatch;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.annotation.DirtiesContext.ClassMode;
+import org.springframework.test.context.ContextConfiguration;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+// tag::example[]
+@CamelSpringTest
+@ContextConfiguration
+// Put here to prevent Spring context caching across tests and test methods since some tests inherit
+// from this test and therefore use the same Spring context. Also because we want to reset the
+// Camel context and mock endpoints between test methods automatically.
+@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);
+ }
+
+ @Test
+ public void testJmx() {
+ assertEquals(DefaultManagementStrategy.class, camelContext.getManagementStrategy().getClass());
+ }
+
+ @Test
+ public void testShutdownTimeout() {
+ assertEquals(10, camelContext.getShutdownStrategy().getTimeout());
+ assertEquals(TimeUnit.SECONDS, camelContext.getShutdownStrategy().getTimeUnit());
+ }
+
+ @Test
+ public void testStopwatch() {
+ StopWatch stopWatch = StopWatchTestExecutionListener.getStopWatch();
+
+ assertNotNull(stopWatch);
+ assertTrue(stopWatch.taken() < 100);
+ }
+
+ @Test
+ public void testExcludedRoute() {
+ assertNotNull(camelContext.getRoute("excludedRoute"));
+ }
+
+ @Test
+ public void testProvidesBreakpoint() {
+ assertNull(camelContext.getDebugger());
+ }
+
+ @Test
+ public void testRouteCoverage() {
+ // noop
+ }
+
+}
+// end::example[]
+
diff --git a/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringPropertiesLocationElementTest.java b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringPropertiesLocationElementTest.java
new file mode 100644
index 0000000..999c5c2
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringPropertiesLocationElementTest.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.spring;
+
+import java.util.List;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Produce;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.component.properties.PropertiesComponent;
+import org.apache.camel.test.spring.junit5.CamelSpringTest;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.ContextConfiguration;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+@CamelSpringTest
+@ContextConfiguration
+@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
+public class CamelSpringPropertiesLocationElementTest {
+ @Autowired
+ protected CamelContext context;
+ @Produce
+ private ProducerTemplate producer;
+ @EndpointInject("mock:result")
+ private MockEndpoint mock;
+
+ @Test
+ public void testPropertiesLocationElement() throws Exception {
+ mock.expectedHeaderReceived("property-1", "property-value-1");
+ mock.expectedHeaderReceived("property-2", "property-value-2");
+ mock.expectedHeaderReceived("property-3", "property-value-3");
+
+ PropertiesComponent pc = context.getComponent("properties", PropertiesComponent.class);
+ assertNotNull(pc, "Properties component not defined");
+
+ List<String> locations = pc.getLocations();
+
+ assertNotNull(locations);
+ assertEquals(4, locations.size(), "Properties locations");
+
+ producer.sendBody("direct:start", null);
+
+ mock.assertIsSatisfied();
+ }
+}
diff --git a/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringProvidesBreakpointInherritedTest.java b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringProvidesBreakpointInherritedTest.java
new file mode 100644
index 0000000..72f2516
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringProvidesBreakpointInherritedTest.java
@@ -0,0 +1,22 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.spring;
+
+public class CamelSpringProvidesBreakpointInherritedTest
+ extends CamelSpringProvidesBreakpointTest {
+
+}
diff --git a/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringProvidesBreakpointTest.java b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringProvidesBreakpointTest.java
new file mode 100644
index 0000000..f4ce323
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringProvidesBreakpointTest.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.spring;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.NamedNode;
+import org.apache.camel.Processor;
+import org.apache.camel.processor.interceptor.BreakpointSupport;
+import org.apache.camel.spi.Breakpoint;
+import org.apache.camel.test.spring.junit5.ProvidesBreakpoint;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class CamelSpringProvidesBreakpointTest
+ extends CamelSpringPlainTest {
+
+ @ProvidesBreakpoint
+ public static Breakpoint createBreakpoint() {
+ return new TestBreakpoint();
+ }
+
+ @Test
+ @Override
+ public void testProvidesBreakpoint() {
+ assertNotNull(camelContext.getDebugger());
+
+ start.sendBody("David");
+
+ assertNotNull(camelContext.getDebugger());
+ assertNotNull(camelContext.getDebugger().getBreakpoints());
+ assertEquals(1, camelContext.getDebugger().getBreakpoints().size());
+
+ assertTrue(camelContext.getDebugger().getBreakpoints().get(0) instanceof TestBreakpoint);
+ assertTrue(((TestBreakpoint) camelContext.getDebugger().getBreakpoints().get(0)).isBreakpointHit());
+ }
+
+ private static final class TestBreakpoint extends BreakpointSupport {
+
+ private boolean breakpointHit;
+
+ @Override
+ public void beforeProcess(Exchange exchange, Processor processor, NamedNode definition) {
+ breakpointHit = true;
+ }
+
+ public boolean isBreakpointHit() {
+ return breakpointHit;
+ }
+ }
+}
diff --git a/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringRouteProcessorDumpRouteCoverageTest.java b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringRouteProcessorDumpRouteCoverageTest.java
new file mode 100644
index 0000000..e49fa8d
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringRouteProcessorDumpRouteCoverageTest.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.spring;
+
+import java.io.File;
+
+import org.apache.camel.management.JmxManagementStrategy;
+import org.apache.camel.test.junit5.TestSupport;
+import org.apache.camel.test.spring.junit5.EnableRouteCoverage;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+@EnableRouteCoverage
+public class CamelSpringRouteProcessorDumpRouteCoverageTest extends CamelSpringPlainTest {
+
+ @BeforeAll
+ public static void prepareFiles() throws Exception {
+ TestSupport.deleteDirectory("target/camel-route-coverage");
+ }
+
+ @Override
+ @Test
+ public void testJmx() {
+ // JMX is enabled with route coverage
+ assertEquals(JmxManagementStrategy.class, camelContext.getManagementStrategy().getClass());
+ }
+
+ @Override
+ public void testRouteCoverage() {
+ camelContext.stop();
+
+ // there should be files
+ String[] names = new File("target/camel-route-coverage").list();
+ assertNotNull(names);
+ assertTrue(names.length > 0);
+ }
+
+}
diff --git a/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringShutdownTimeoutInheritedOverrideTest.java b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringShutdownTimeoutInheritedOverrideTest.java
new file mode 100644
index 0000000..b4f4d75
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringShutdownTimeoutInheritedOverrideTest.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.spring;
+
+import java.util.concurrent.TimeUnit;
+
+import org.apache.camel.test.spring.junit5.ShutdownTimeout;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+@ShutdownTimeout
+public class CamelSpringShutdownTimeoutInheritedOverrideTest
+ extends CamelSpringShutdownTimeoutTest {
+
+ @Test
+ @Override
+ public void testShutdownTimeout() {
+ assertEquals(10, camelContext.getShutdownStrategy().getTimeout());
+ assertEquals(TimeUnit.SECONDS, camelContext.getShutdownStrategy().getTimeUnit());
+ }
+}
diff --git a/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringShutdownTimeoutInheritedTest.java b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringShutdownTimeoutInheritedTest.java
new file mode 100644
index 0000000..9e2aacc
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringShutdownTimeoutInheritedTest.java
@@ -0,0 +1,22 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.spring;
+
+public class CamelSpringShutdownTimeoutInheritedTest
+ extends CamelSpringShutdownTimeoutTest {
+
+}
diff --git a/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringShutdownTimeoutTest.java b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringShutdownTimeoutTest.java
new file mode 100644
index 0000000..60bc496
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringShutdownTimeoutTest.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.spring;
+
+import java.util.concurrent.TimeUnit;
+
+import org.apache.camel.test.spring.junit5.ShutdownTimeout;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+@ShutdownTimeout(value = 11, timeUnit = TimeUnit.MILLISECONDS)
+public class CamelSpringShutdownTimeoutTest
+ extends CamelSpringPlainTest {
+
+ @Test
+ @Override
+ public void testShutdownTimeout() {
+ assertEquals(11, camelContext.getShutdownStrategy().getTimeout());
+ assertEquals(TimeUnit.MILLISECONDS, camelContext.getShutdownStrategy().getTimeUnit());
+ }
+}
diff --git a/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringTestPropertySourceTest.java b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringTestPropertySourceTest.java
new file mode 100644
index 0000000..0f61cce
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringTestPropertySourceTest.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.spring;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Produce;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.spring.junit5.CamelSpringTest;
+import org.junit.jupiter.api.Test;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.TestPropertySource;
+
+@CamelSpringTest
+@ContextConfiguration
+@TestPropertySource(properties = "fixedBody=Camel")
+public class CamelSpringTestPropertySourceTest {
+
+ @Produce("direct:in")
+ private ProducerTemplate start;
+
+ @EndpointInject("mock:out")
+ private MockEndpoint end;
+
+ @Test
+ public void readsFileAndInlinedPropertiesFromAnnotation() throws Exception {
+ end.expectedBodiesReceived("Camel");
+
+ start.sendBody("Aardvark");
+
+ end.assertIsSatisfied();
+ }
+}
diff --git a/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringTestSupportActiveProfileTest.java b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringTestSupportActiveProfileTest.java
new file mode 100644
index 0000000..b697632
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringTestSupportActiveProfileTest.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.spring;
+
+import org.apache.camel.test.spring.junit5.CamelSpringTestSupport;
+import org.junit.jupiter.api.Test;
+import org.springframework.context.support.AbstractApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+// START SNIPPET: e1
+
+/**
+ * Just extend the CamelSpringTestSupport and use Camel test kit for easy Camel based unit testing.
+ */
+public class CamelSpringTestSupportActiveProfileTest extends CamelSpringTestSupport {
+
+ @Override
+ protected AbstractApplicationContext createApplicationContext() {
+ // must not refresh when using active profiles
+ // lets reuse the xml file from the other test
+ return new ClassPathXmlApplicationContext(new String[]{"org/apache/camel/test/spring/CamelSpringActiveProfileTest-context.xml"}, false);
+ }
+
+ @Override
+ protected String[] activeProfiles() {
+ // return the active profiles to be used
+ return new String[]{"test"};
+ }
+
+ @Test
+ public void testLoadActiveProfile() throws InterruptedException {
+ getMockEndpoint("mock:test").expectedBodiesReceived("Hello World");
+ template.sendBody("direct:start", "World");
+ assertMockEndpointsSatisfied();
+ }
+
+}
+// END SNIPPET: e1
diff --git a/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringUseAdviceWithTest.java b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringUseAdviceWithTest.java
new file mode 100644
index 0000000..a8125f2
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringUseAdviceWithTest.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.spring;
+
+import org.apache.camel.ServiceStatus;
+import org.apache.camel.test.spring.junit5.StopWatchTestExecutionListener;
+import org.apache.camel.test.spring.junit5.UseAdviceWith;
+import org.apache.camel.util.StopWatch;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+@UseAdviceWith
+public class CamelSpringUseAdviceWithTest extends CamelSpringPlainTest {
+
+ @BeforeEach
+ public void testContextStarted() throws Exception {
+ assertEquals(ServiceStatus.Stopped, camelContext.getStatus());
+ camelContext.start();
+
+ // just sleep a little to simulate testing take a bit time
+ Thread.sleep(1000);
+ }
+
+ @Override
+ @Test
+ public void testStopwatch() {
+ StopWatch stopWatch = StopWatchTestExecutionListener.getStopWatch();
+
+ assertNotNull(stopWatch);
+ long taken = stopWatch.taken();
+ assertTrue(taken > 0, taken + " > 0, but was: " + taken);
+ assertTrue(taken < 3000, taken + " < 3000, but was: " + taken);
+ }
+}
diff --git a/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/TestPropertyInjectRouteBuilder.java b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/TestPropertyInjectRouteBuilder.java
new file mode 100644
index 0000000..bf10a05
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/TestPropertyInjectRouteBuilder.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.spring;
+
+import org.apache.camel.PropertyInject;
+import org.apache.camel.builder.RouteBuilder;
+
+public class TestPropertyInjectRouteBuilder extends RouteBuilder {
+
+ @PropertyInject("{{property.to.override}}")
+ private String propertyToOverride;
+
+ @Override
+ public void configure() {
+ from("direct:start-override-route")
+ .transform(constant(propertyToOverride));
+ }
+
+}
diff --git a/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/TestRouteBuilder.java b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/TestRouteBuilder.java
new file mode 100644
index 0000000..ef5eb2d
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/TestRouteBuilder.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.spring;
+
+import org.apache.camel.builder.RouteBuilder;
+
+public class TestRouteBuilder extends RouteBuilder {
+
+ @Override
+ public void configure() {
+ from("direct:z")
+ .routeId("excludedRoute")
+ .to("log:org.apache.camel.test.spring.junit5");
+ }
+}
diff --git a/components/camel-test-spring-junit5/src/test/resources/jndi.properties b/components/camel-test-spring-junit5/src/test/resources/jndi.properties
new file mode 100644
index 0000000..7f9b32b
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/resources/jndi.properties
@@ -0,0 +1,22 @@
+## ---------------------------------------------------------------------------
+## Licensed to the Apache Software Foundation (ASF) under one or more
+## contributor license agreements. See the NOTICE file distributed with
+## this work for additional information regarding copyright ownership.
+## The ASF licenses this file to You under the Apache License, Version 2.0
+## (the "License"); you may not use this file except in compliance with
+## the License. You may obtain a copy of the License at
+##
+## http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+## ---------------------------------------------------------------------------
+
+# START SNIPPET: jndi
+
+java.naming.factory.initial = org.apache.camel.support.jndi.CamelInitialContextFactory
+
+# END SNIPPET: jndi
diff --git a/components/camel-test-spring-junit5/src/test/resources/log4j2.properties b/components/camel-test-spring-junit5/src/test/resources/log4j2.properties
new file mode 100644
index 0000000..4e9ce60
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/resources/log4j2.properties
@@ -0,0 +1,30 @@
+## ---------------------------------------------------------------------------
+## Licensed to the Apache Software Foundation (ASF) under one or more
+## contributor license agreements. See the NOTICE file distributed with
+## this work for additional information regarding copyright ownership.
+## The ASF licenses this file to You under the Apache License, Version 2.0
+## (the "License"); you may not use this file except in compliance with
+## the License. You may obtain a copy of the License at
+##
+## http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+## ---------------------------------------------------------------------------
+
+appender.file.type = File
+appender.file.name = file
+appender.file.fileName = target/camel-test-spring.log
+appender.file.layout.type = PatternLayout
+appender.file.layout.pattern = %d %-5p %c{1} - %m %n
+appender.out.type = Console
+appender.out.name = out
+appender.out.layout.type = PatternLayout
+appender.out.layout.pattern = [%30.30t] %-30.30c{1} %-5p %m%n
+logger.spring.name = org.apache.camel.test.spring
+logger.spring.level = DEBUG
+rootLogger.level = INFO
+rootLogger.appenderRef.file.ref = file
diff --git a/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/issues/AdviceWithInterceptSendToEndpointWithLoadbalancerTest.xml b/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/issues/AdviceWithInterceptSendToEndpointWithLoadbalancerTest.xml
new file mode 100644
index 0000000..99ad54d
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/issues/AdviceWithInterceptSendToEndpointWithLoadbalancerTest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:camel="http://camel.apache.org/schema/spring"
+ 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 ">
+
+ <bean id="route"
+ class="org.apache.camel.test.issues.AdviceWithInterceptSendToEndpointWithLoadbalancerTest.LoadbalancerTestRoute" />
+
+ <camelContext
+ xmlns="http://camel.apache.org/schema/spring">
+ <camel:routeBuilder ref="route" />
+ </camelContext>
+</beans>
\ No newline at end of file
diff --git a/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/issues/AdviceWithOnCompletionTest.xml b/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/issues/AdviceWithOnCompletionTest.xml
new file mode 100644
index 0000000..a75147a
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/issues/AdviceWithOnCompletionTest.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:camel="http://camel.apache.org/schema/spring"
+ 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
+ xmlns="http://camel.apache.org/schema/spring">
+
+ <onCompletion>
+ <to uri="mock:complete" />
+ </onCompletion>
+
+ <route>
+ <from uri="file:start" />
+ <to uri="log:end" />
+ </route>
+
+ </camelContext>
+</beans>
\ No newline at end of file
diff --git a/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/issues/AdviceWithOnExceptionMultipleIssueTest.xml b/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/issues/AdviceWithOnExceptionMultipleIssueTest.xml
new file mode 100644
index 0000000..a86f494
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/issues/AdviceWithOnExceptionMultipleIssueTest.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:camel="http://camel.apache.org/schema/spring"
+ 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
+ xmlns="http://camel.apache.org/schema/spring">
+
+ <onException>
+ <exception>java.lang.Exception</exception>
+ <handled>
+ <constant>true</constant>
+ </handled>
+ <to uri="mock:error" />
+ </onException>
+
+ <route id="RouteA">
+ <from uri="direct:startA" />
+ <to uri="mock:resultA" />
+ </route>
+
+ <route id="RouteB">
+ <from uri="direct:startB" />
+ <to uri="mock:resultB" />
+ </route>
+
+ </camelContext>
+
+</beans>
\ No newline at end of file
diff --git a/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/issues/MockEndpointsAndSkipTest.xml b/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/issues/MockEndpointsAndSkipTest.xml
new file mode 100644
index 0000000..9e8e4d8
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/issues/MockEndpointsAndSkipTest.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:camel="http://camel.apache.org/schema/spring"
+ 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
+ xmlns="http://camel.apache.org/schema/spring">
+
+ <route>
+ <from uri="direct:start" />
+ <to uri="log:foo" />
+ <to uri="seda:foo" />
+ </route>
+
+ </camelContext>
+
+</beans>
\ No newline at end of file
diff --git a/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/patterns/ProduceBeanInjectTest.xml b/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/patterns/ProduceBeanInjectTest.xml
new file mode 100644
index 0000000..b12f2c1
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/patterns/ProduceBeanInjectTest.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:camel="http://camel.apache.org/schema/spring"
+ 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" />
+ <transform>
+ <simple>${in.body} rocks!</simple>
+ </transform>
+ </route>
+ </camelContext>
+
+ <!--bean id="camelPostProcessBean" class="org.apache.camel.spring.CamelBeanPostProcessor"
+ / -->
+
+ <bean id="myProduceBean"
+ class="org.apache.camel.test.patterns.MyProduceBean" />
+
+</beans>
\ No newline at end of file
diff --git a/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/patterns/ProduceBeanTest.xml b/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/patterns/ProduceBeanTest.xml
new file mode 100644
index 0000000..25b5d92
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/patterns/ProduceBeanTest.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:camel="http://camel.apache.org/schema/spring"
+ 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" />
+ <bean beanType="org.apache.camel.test.patterns.MyProduceBean" />
+ </route>
+ </camelContext>
+
+</beans>
\ No newline at end of file
diff --git a/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/patterns/SimpleMockTest.xml b/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/patterns/SimpleMockTest.xml
new file mode 100644
index 0000000..b735cd5
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/patterns/SimpleMockTest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<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
+ xmlns="http://camel.apache.org/schema/spring">
+ <route>
+ <from uri="direct:start" />
+ <to uri="mock:result" />
+ </route>
+ </camelContext>
+
+</beans>
\ No newline at end of file
diff --git a/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/patterns/applicationContext.xml b/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/patterns/applicationContext.xml
new file mode 100644
index 0000000..ee4c88d
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/patterns/applicationContext.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:camel="http://camel.apache.org/schema/spring"
+ 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" trace="true"
+ autoStartup="true">
+
+ <route>
+ <from uri="direct:start" />
+ <to uri="mock:a" />
+ <transform>
+ <simple>Hello ${body}</simple>
+ </transform>
+ <to uri="mock:b" />
+ </route>
+ </camelContext>
+
+</beans>
\ No newline at end of file
diff --git a/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/spring/CamelSpringActiveProfileTest-context.xml b/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/spring/CamelSpringActiveProfileTest-context.xml
new file mode 100644
index 0000000..d05491a
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/spring/CamelSpringActiveProfileTest-context.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:camel="http://camel.apache.org/schema/spring"
+ 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" />
+ <transform>
+ <simple>Hello ${body}</simple>
+ </transform>
+ <to uri="properties:{{cool.end}}" />
+ </route>
+ </camelContext>
+
+ <!-- setup the profile for testing -->
+ <beans profile="test">
+ <bean id="bridgePropertyPlaceholder"
+ class="org.apache.camel.spring.spi.BridgePropertyPlaceholderConfigurer">
+ <property name="location"
+ value="classpath:org/apache/camel/test/spring/test.properties" />
+ </bean>
+ </beans>
+</beans>
\ No newline at end of file
diff --git a/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/spring/CamelSpringOverridePropertiesForPropertyInjectTest-context.xml b/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/spring/CamelSpringOverridePropertiesForPropertyInjectTest-context.xml
new file mode 100644
index 0000000..a1ad878
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/spring/CamelSpringOverridePropertiesForPropertyInjectTest-context.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<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 ">
+
+ <bean id="bridgePropertyPlaceholder"
+ class="org.apache.camel.spring.spi.BridgePropertyPlaceholderConfigurer">
+ <property name="location"
+ value="classpath:org/apache/camel/test/spring/test.properties" />
+ </bean>
+
+ <bean id="testRouteBuilder"
+ class="org.apache.camel.test.spring.TestPropertyInjectRouteBuilder"></bean>
+
+ <camelContext id="camelContext"
+ xmlns="http://camel.apache.org/schema/spring">
+ <routeBuilder ref="testRouteBuilder" />
+ </camelContext>
+
+</beans>
\ No newline at end of file
diff --git a/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/spring/CamelSpringOverridePropertiesTest-context.xml b/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/spring/CamelSpringOverridePropertiesTest-context.xml
new file mode 100644
index 0000000..9faf7d3
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/spring/CamelSpringOverridePropertiesTest-context.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<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 ">
+
+ <bean id="bridgePropertyPlaceholder"
+ class="org.apache.camel.spring.spi.BridgePropertyPlaceholderConfigurer">
+ <property name="location"
+ value="classpath:org/apache/camel/test/spring/test.properties" />
+ </bean>
+
+ <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="{{cool.end}}" />
+ </route>
+ </camelContext>
+
+
+</beans>
\ No newline at end of file
diff --git a/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/spring/CamelSpringPlainTest-context.xml b/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/spring/CamelSpringPlainTest-context.xml
new file mode 100644
index 0000000..44299d8
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/spring/CamelSpringPlainTest-context.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<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" trace="true"
+ autoStartup="true">
+ <packageScan>
+ <package>org.apache.camel.test.spring</package>
+ </packageScan>
+ <route>
+ <from uri="direct:start" />
+ <to uri="mock:a" />
+ <transform>
+ <simple>Hello ${body}</simple>
+ </transform>
+ <to uri="mock:b" />
+ </route>
+ </camelContext>
+
+ <bean id="bridgePropertyPlaceholder"
+ class="org.apache.camel.spring.spi.BridgePropertyPlaceholderConfigurer">
+ <property name="location"
+ value="classpath:org/apache/camel/test/spring/test.properties" />
+ </bean>
+
+</beans>
\ No newline at end of file
diff --git a/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/spring/CamelSpringPropertiesLocationElementTest-context.xml b/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/spring/CamelSpringPropertiesLocationElementTest-context.xml
new file mode 100644
index 0000000..c506b8d
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/spring/CamelSpringPropertiesLocationElementTest-context.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<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
+ xmlns="http://camel.apache.org/schema/spring">
+ <propertyPlaceholder
+ id="property-placeholder-camel"
+ location="classpath:org/apache/camel/test/spring/properties-location-element-3.properties">
+ <propertiesLocation resolver="classpath"
+ path="org/apache/camel/test/spring/properties-location-element-1.properties" />
+ <propertiesLocation resolver="classpath"
+ path="org/apache/camel/test/spring/properties-location-element-2.properties" />
+ <propertiesLocation resolver="classpath"
+ path="org/apache/camel/test/spring/properties-location-element-4.properties"
+ optional="true" />
+ </propertyPlaceholder>
+
+ <route>
+ <from uri="direct:start" />
+ <setHeader name="property-1">
+ <constant>{{property-key-1}}</constant>
+ </setHeader>
+ <setHeader name="property-2">
+ <constant>{{property-key-2}}</constant>
+ </setHeader>
+ <setHeader name="property-3">
+ <constant>{{property-key-3}}</constant>
+ </setHeader>
+ <to uri="mock:result" />
+ </route>
+
+ </camelContext>
+
+</beans>
diff --git a/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/spring/CamelSpringTestPropertySourceTest-context.xml b/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/spring/CamelSpringTestPropertySourceTest-context.xml
new file mode 100644
index 0000000..e71b158
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/spring/CamelSpringTestPropertySourceTest-context.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<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">
+
+ <!-- Enable PropertySource -->
+ <bean
+ class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer" />
+
+ <bean id="myBean" class="org.apache.camel.ValueHolder">
+ <constructor-arg value="${fixedBody}" /> <!-- configured from @TestPropertySource -->
+ </bean>
+
+ <camelContext id="camelContext"
+ xmlns="http://camel.apache.org/schema/spring" trace="true"
+ autoStartup="true">
+ <route>
+ <from uri="direct:in" />
+ <bean ref="myBean" method="get" />
+ <to uri="mock:out" />
+ </route>
+ </camelContext>
+
+</beans>
\ No newline at end of file
diff --git a/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/spring/properties-location-element-1.properties b/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/spring/properties-location-element-1.properties
new file mode 100644
index 0000000..81ff2b5
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/spring/properties-location-element-1.properties
@@ -0,0 +1,18 @@
+## ---------------------------------------------------------------------------
+## Licensed to the Apache Software Foundation (ASF) under one or more
+## contributor license agreements. See the NOTICE file distributed with
+## this work for additional information regarding copyright ownership.
+## The ASF licenses this file to You under the Apache License, Version 2.0
+## (the "License"); you may not use this file except in compliance with
+## the License. You may obtain a copy of the License at
+##
+## http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+## ---------------------------------------------------------------------------
+
+property-key-1 = property-value-1
diff --git a/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/spring/properties-location-element-2.properties b/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/spring/properties-location-element-2.properties
new file mode 100644
index 0000000..24ebe3f
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/spring/properties-location-element-2.properties
@@ -0,0 +1,18 @@
+## ---------------------------------------------------------------------------
+## Licensed to the Apache Software Foundation (ASF) under one or more
+## contributor license agreements. See the NOTICE file distributed with
+## this work for additional information regarding copyright ownership.
+## The ASF licenses this file to You under the Apache License, Version 2.0
+## (the "License"); you may not use this file except in compliance with
+## the License. You may obtain a copy of the License at
+##
+## http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+## ---------------------------------------------------------------------------
+
+property-key-2 = property-value-2
diff --git a/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/spring/properties-location-element-3.properties b/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/spring/properties-location-element-3.properties
new file mode 100644
index 0000000..6c94f7f
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/spring/properties-location-element-3.properties
@@ -0,0 +1,18 @@
+## ---------------------------------------------------------------------------
+## Licensed to the Apache Software Foundation (ASF) under one or more
+## contributor license agreements. See the NOTICE file distributed with
+## this work for additional information regarding copyright ownership.
+## The ASF licenses this file to You under the Apache License, Version 2.0
+## (the "License"); you may not use this file except in compliance with
+## the License. You may obtain a copy of the License at
+##
+## http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+## ---------------------------------------------------------------------------
+
+property-key-3 = property-value-3
diff --git a/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/spring/test.properties b/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/spring/test.properties
new file mode 100644
index 0000000..4fd73b6
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/spring/test.properties
@@ -0,0 +1,19 @@
+## ---------------------------------------------------------------------------
+## Licensed to the Apache Software Foundation (ASF) under one or more
+## contributor license agreements. See the NOTICE file distributed with
+## this work for additional information regarding copyright ownership.
+## The ASF licenses this file to You under the Apache License, Version 2.0
+## (the "License"); you may not use this file except in compliance with
+## the License. You may obtain a copy of the License at
+##
+## http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+## ---------------------------------------------------------------------------
+
+cool.end=mock:test
+property.to.override=This value should be overriden
diff --git a/components/pom.xml b/components/pom.xml
index 6f512fc..1a0d396 100644
--- a/components/pom.xml
+++ b/components/pom.xml
@@ -67,6 +67,7 @@
<module>camel-testcontainers</module>
<module>camel-testcontainers-spring</module>
<module>camel-test-junit5</module>
+ <module>camel-test-spring-junit5</module>
<module>camel-blueprint</module>
<module>camel-spring</module>
<module>camel-groovy</module>
diff --git a/docs/components/modules/ROOT/nav.adoc b/docs/components/modules/ROOT/nav.adoc
index 524e483..0a3ca76 100644
--- a/docs/components/modules/ROOT/nav.adoc
+++ b/docs/components/modules/ROOT/nav.adoc
@@ -351,6 +351,7 @@
* xref:test-cdi.adoc[CDI Testing]
* xref:test-junit5.adoc[Test Module]
* xref:test-karaf.adoc[Test Karaf]
+* xref:test-spring-junit5.adoc[Camel Test Spring JUnit 5]
* xref:test-spring.adoc[Test Spring]
* xref:test.adoc[Test Module]
* xref:testcontainers-spring.adoc[Testcontainers Spring]
diff --git a/docs/components/modules/ROOT/pages/test-spring-junit5.adoc b/docs/components/modules/ROOT/pages/test-spring-junit5.adoc
new file mode 100644
index 0000000..dcf5242
--- /dev/null
+++ b/docs/components/modules/ROOT/pages/test-spring-junit5.adoc
@@ -0,0 +1,141 @@
+= Camel Test Spring JUnit 5
+:page-source: components/camel-test-spring-junit5/src/main/docs/test-spring-junit5.adoc
+
+*Available since 3.0*
+
+The `camel-test-spring-junit5` module makes it possible to test Camel Spring based applications with JUnit 5.
+
+Testing is a crucial part of any development or integration work. The Spring Framework offers a number of features that makes it easy to test while using Spring for Inversion of Control.
+
+There are multiple approaches to test Camel Spring 5.x based routes with JUnit 5.
+
+== Extending the CamelSpringTestSupport class
+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() {
+ 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();
+ }
+}
+----
+
+This approach provides feature parity with `org.apache.camel.test.junit5.CamelTestSupport` from xref:components::test-junit5.adoc[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.
+[source,java]
+----
+protected abstract AbstractApplicationContext createApplicationContext();
+----
+
+== Using the @CamelSpringTest annotation
+Another approach involves the usage of the `org.apache.camel.test.spring.junit5.CamelSpringTest` annotation, for instance:
+----
+@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);
+ }
+
+ @Test
+ public void testAnotherCase() throws Exception {
+ ...
+ }
+}
+----
+
+The above test will load the route from `org/apache/camel/test/spring/CamelSpringPlainTest-context.xml` which looks like below:
+----
+<?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" trace="true"
+ autoStartup="true">
+ <packageScan>
+ <package>org.apache.camel.test.spring</package>
+ </packageScan>
+ <route>
+ <from uri="direct:start" />
+ <to uri="mock:a" />
+ <transform>
+ <simple>Hello ${body}</simple>
+ </transform>
+ <to uri="mock:b" />
+ </route>
+ </camelContext>
+
+ <bean id="bridgePropertyPlaceholder"
+ class="org.apache.camel.spring.spi.BridgePropertyPlaceholderConfigurer">
+ <property name="location"
+ value="classpath:org/apache/camel/test/spring/test.properties" />
+ </bean>
+</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`.
+
+== 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.
+
+=== Referencing the Camel Test Spring JUnit 5 library in your project
+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>
+----
+
+Tips: 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 to migrate a Camel Spring test at once.
+
+=== Typical migration steps linked to JUnit 5 support in Camel Test Spring
+* Migration steps linked to xref:components::test-junit5.adoc[JUnit 5 support in Camel Test itself] 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`
diff --git a/parent/pom.xml b/parent/pom.xml
index a706510..1a94e61 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -2258,6 +2258,11 @@
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
+ <artifactId>camel-test-spring-junit5</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
<artifactId>camel-test-karaf</artifactId>
<version>${project.version}</version>
</dependency>
diff --git a/platforms/spring-boot/spring-boot-dm/camel-spring-boot-dependencies/pom.xml b/platforms/spring-boot/spring-boot-dm/camel-spring-boot-dependencies/pom.xml
index 41ecbd5..bb42363 100644
--- a/platforms/spring-boot/spring-boot-dm/camel-spring-boot-dependencies/pom.xml
+++ b/platforms/spring-boot/spring-boot-dm/camel-spring-boot-dependencies/pom.xml
@@ -3155,6 +3155,11 @@
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
+ <artifactId>camel-test-spring-junit5</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
<artifactId>camel-test-karaf</artifactId>
<version>${project.version}</version>
</dependency>