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 &quot;<code>-context.xml</code>&quot;.
+     */
+    @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[] {&quot;test-context.xml&quot;}, 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>