[camel] branch CAMEL-13965 created (now 59b1dde)

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

[camel] branch CAMEL-13965 created (now 59b1dde)

aldettinger
This is an automated email from the ASF dual-hosted git repository.

aldettinger pushed a change to branch CAMEL-13965
in repository https://gitbox.apache.org/repos/asf/camel.git.


      at 59b1dde  CAMEL-13965: Initial import of camel-test-spring-junit5 based on camel-test-spring

This branch includes the following new commits:

     new 59b1dde  CAMEL-13965: Initial import of camel-test-spring-junit5 based on camel-test-spring

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Reply | Threaded
Open this post in threaded view
|

[camel] 01/01: CAMEL-13965: Initial import of camel-test-spring-junit5 based on camel-test-spring

aldettinger
This is an automated email from the ASF dual-hosted git repository.

aldettinger pushed a commit to branch CAMEL-13965
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 59b1dde6d6bbe7f1a27686eca09009b2daa7ec11
Author: aldettinger <[hidden email]>
AuthorDate: Wed Sep 11 10:15:41 2019 +0200

    CAMEL-13965: Initial import of 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        |  74 +++
 .../src/main/docs/test-spring.adoc                 | 459 +++++++++++++++++
 .../camel/test/spring/CamelAnnotationsHandler.java | 367 ++++++++++++++
 .../spring/CamelSpringBootExecutionListener.java   |  95 ++++
 .../spring/CamelSpringBootJUnit4ClassRunner.java   |  33 ++
 .../camel/test/spring/CamelSpringBootRunner.java   |  87 ++++
 .../CamelSpringDelegatingTestContextLoader.java    | 138 ++++++
 .../test/spring/CamelSpringJUnit4ClassRunner.java  |  33 ++
 .../camel/test/spring/CamelSpringRunner.java       |  83 ++++
 .../test/spring/CamelSpringTestContextLoader.java  | 551 +++++++++++++++++++++
 ...ringTestContextLoaderTestExecutionListener.java |  50 ++
 .../camel/test/spring/CamelSpringTestHelper.java   | 109 ++++
 .../camel/test/spring/CamelSpringTestSupport.java  | 211 ++++++++
 .../test/spring/CamelTestContextBootstrapper.java  |  31 ++
 .../org/apache/camel/test/spring/DisableJmx.java   |  43 ++
 .../spring/DisableJmxTestExecutionListener.java    |  39 ++
 .../camel/test/spring/EnableRouteCoverage.java     |  41 ++
 .../apache/camel/test/spring/ExcludeRoutes.java    |  44 ++
 .../apache/camel/test/spring/MockEndpoints.java    |  43 ++
 .../camel/test/spring/MockEndpointsAndSkip.java    |  43 ++
 .../camel/test/spring/ProvidesBreakpoint.java      |  36 ++
 .../camel/test/spring/RouteCoverageDumper.java     |  82 +++
 .../test/spring/RouteCoverageEventNotifier.java    |  51 ++
 .../apache/camel/test/spring/ShutdownTimeout.java  |  49 ++
 .../spring/StopWatchTestExecutionListener.java     |  62 +++
 .../apache/camel/test/spring/UseAdviceWith.java    |  49 ++
 ...eOverridePropertiesWithPropertiesComponent.java |  34 ++
 ...nterceptSendToEndpointWithLoadbalancerTest.java |  68 +++
 .../test/issues/AdviceWithOnCompletionTest.java    |  61 +++
 .../AdviceWithOnExceptionMultipleIssueTest.java    | 117 +++++
 .../test/issues/MockEndpointsAndSkipTest.java      |  46 ++
 .../test/patterns/DebugSpringCamelContextTest.java |  40 ++
 .../camel/test/patterns/DebugSpringTest.java       |  81 +++
 .../apache/camel/test/patterns/MyProduceBean.java  |  41 ++
 .../org/apache/camel/test/patterns/MySender.java   |  25 +
 .../camel/test/patterns/ProduceBeanTest.java       |  42 ++
 .../test/patterns/ProducerBeanInjectTest.java      |  38 ++
 .../apache/camel/test/patterns/SimpleMockTest.java |  63 +++
 .../test/spring/CamelSpringActiveProfileTest.java  |  57 +++
 ...ingOverridePropertiesForPropertyInjectTest.java |  57 +++
 .../spring/CamelSpringOverridePropertiesTest.java  |  72 +++
 .../CamelSpringPropertiesLocationElementTest.java  |  67 +++
 ...lSpringRouteProcessorDumpRouteCoverageTest.java |  55 ++
 ...pringRunnerDisableJmxInheritedOverrideTest.java |  33 ++
 .../CamelSpringRunnerDisableJmxInheritedTest.java  |  21 +
 .../spring/CamelSpringRunnerDisableJmxTest.java    |  33 ++
 .../spring/CamelSpringRunnerExcludeRoutesTest.java |  32 ++
 .../test/spring/CamelSpringRunnerPlainTest.java    | 113 +++++
 ...ringRunnerProvidesBreakpointInherritedTest.java |  22 +
 .../CamelSpringRunnerProvidesBreakpointTest.java   |  66 +++
 ...RunnerShutdownTimeoutInheritedOverrideTest.java |  34 ++
 ...elSpringRunnerShutdownTimeoutInheritedTest.java |  22 +
 .../CamelSpringRunnerShutdownTimeoutTest.java      |  34 ++
 .../CamelSpringRunnerTestPropertySourceTest.java   |  49 ++
 .../spring/CamelSpringRunnerUseAdviceWithTest.java |  50 ++
 .../CamelSpringTestSupportActiveProfileTest.java   |  51 ++
 .../spring/TestPropertyInjectRouteBuilder.java     |  33 ++
 .../apache/camel/test/spring/TestRouteBuilder.java |  30 ++
 .../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 ++
 ...SpringPropertiesLocationElementTest-context.xml |  56 +++
 .../spring/CamelSpringRunnerPlainTest-context.xml  |  48 ++
 ...lSpringRunnerTestPropertySourceTest-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 +
 parent/pom.xml                                     |   5 +
 .../camel-spring-boot-dependencies/pom.xml         |   5 +
 83 files changed, 5233 insertions(+)

diff --git a/apache-camel/pom.xml b/apache-camel/pom.xml
index b35aba0..362e50d 100644
--- a/apache-camel/pom.xml
+++ b/apache-camel/pom.xml
@@ -1498,6 +1498,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 09b0844..af62124 100644
--- a/apache-camel/src/main/descriptors/common-bin.xml
+++ b/apache-camel/src/main/descriptors/common-bin.xml
@@ -320,6 +320,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 518d5d6..6c41d2e 100644
--- a/bom/camel-bom/pom.xml
+++ b/bom/camel-bom/pom.xml
@@ -2905,6 +2905,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..9d49c1f
--- /dev/null
+++ b/components/camel-test-spring-junit5/pom.xml
@@ -0,0 +1,74 @@
+<?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</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-impl</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.adoc b/components/camel-test-spring-junit5/src/main/docs/test-spring.adoc
new file mode 100644
index 0000000..016191a
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/main/docs/test-spring.adoc
@@ -0,0 +1,459 @@
+= Test Spring
+
+*Available since 2.10*
+
+Allows to test Camel with Spring applications such as Spring XML files or Spring-Boot.
+
+[IMPORTANT]
+====
+This documentation is old and needs to be updated
+====
+
+xref:manual::testing.adoc[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 which works with JUnit 3.x, JUnit 4.x, and http://testng.org[TestNG].
+
+We can use Spring for IoC and the Camel xref:components::mock-component.adoc[Mock] and xref:components::test.adoc[Test] endpoints to create sophisticated integration/unit tests that are easy to run and debug inside your IDE.  There are three supported approaches for testing with Spring in Camel.
+[width="100%",cols="1,1,4,1",options="header",]
+|=======================================================================
+|Name |Testing Frameworks Supported |Description |Required Camel Test Dependencies
+|<<camel-spring-test-support,Camel Spring Test Support>> a|
+* JUnit 3.x (deprecated)
+* JUnit 4.x
+* TestNG
+
+a|
+Provided by:
+
+* `org.apache.camel.test.CamelSpringTestSupport`
+* `org.apache.camel.test.junit4.CamelSpringTestSupport`
+* `org.apache.camel.testng.CamelSpringTestSupport`
+
+These base classes provide feature parity with the simple `CamelTestSupport` classes from xref:components::test.adoc[Camel Test] but do not support Spring annotations on the test class such as `@Autowired`, `@DirtiesContext`, and `@ContextConfiguration`.
+
+a|
+* JUnit 3.x (deprecated) - camel-test-spring
+* JUnit 4.x - camel-test-spring
+* TestNG - camel-test-ng
+
+|<<plain-spring-test, Plain Spring Test>> a|
+* JUnit 3.x
+* JUnit 4.x
+* TestNG
+
+a|
+Either extend the abstract base classes:
+
+* `org.springframework.test.context.junit38.AbstractJUnit38SpringContextTests`
+* `org.springframework.test.context.junit38.AbstractJUnit4SpringContextTests`
+* etc.
+
+provided in Spring Test or use the Spring Test JUnit4 runner.
+
+These approaches support both the Camel annotations and Spring annotations. However, they do NOT have http://camel.apache.org/camel-test.html#CamelTest-FeaturesProvidedbyCamelTestSupport[feature parity] with:
+
+* `org.apache.camel.test.CamelTestSupport`
+* `org.apache.camel.test.junit4.CamelTestSupport`
+* `org.apache.camel.testng.CamelSpringTestSupport`
+
+a|
+* JUnit 3.x (deprecated) - None
+* JUnit 4.x - None
+* TestNG - None
+
+|<<camel-enhanced-spring-test,Camel Enhanced Spring Test>> a|
+* JUnit 4.x
+* TestNG
+
+a|
+Either:
+
+* use the `org.apache.camel.test.junit4.CamelSpringJUnit4ClassRunner` runner with the `@RunWith` annotation,
+* or extend `org.apache.camel.testng.AbstractCamelTestNGSpringContextTests` to enable http://camel.apache.org/camel-test.html#CamelTest-FeaturesProvidedbyCamelTestSupport[feature parity] with `org.apache.camel.test.CamelTestSupport` and `org.apache.camel.test.junit4.CamelTestSupport`. These classes support the full suite of Spring Test annotations such as `@Autowired`, `@DirtiesContext`, and `@ContextConfiguration`.
+
+a|
+* JUnit 3.x (deprecated) - camel-test-spring
+* JUnit 4.x - camel-test-spring
+* TestNG - camel-test-ng
+|=======================================================================
+
+[#camel-spring-test-support]
+== CamelSpringTestSupport
+
+The following Spring test support classes:
+
+* `org.apache.camel.test.CamelSpringTestSupport`
+* `org.apache.camel.test.junit4.CamelSpringTestSupport`, and
+* `org.apache.camel.testng.CamelSpringTestSupport`
+
+extend their non-Spring aware counterparts:
+
+* `org.apache.camel.test.CamelTestSupport`
+* `org.apache.camel.test.junit4.CamelTestSupport`, and
+* `org.apache.camel.testng.CamelTestSupport`
+
+and deliver integration with Spring into your test classes.
+
+Instead of instantiating the `CamelContext` and routes programmatically, these classes rely on a Spring context to wire the needed components together.  If your test extends one of these classes, you must provide the Spring context by implementing the following method.
+[source,java]
+----
+protected abstract AbstractApplicationContext createApplicationContext();
+----
+You are responsible for the instantiation of the Spring context in the method implementation.  All of the features available in the non-Spring aware counterparts from http://camel.apache.org/camel-test.html[Camel Test] are available in your test.
+
+[#plain-spring-test]
+== Plain Spring Test
+
+In this approach, your test classes directly inherit from the Spring Test abstract test classes or use the JUnit 4.x test runner provided in Spring Test.  This approach supports dependency injection into your test class and the full suite of Spring Test annotations. However, it does not support the features provided by the `CamelSpringTestSupport` classes.
+
+=== Plain Spring Test using JUnit 3.x with XML Config Example
+
+Here is a simple unit test using JUnit 3.x support from Spring Test using http://svn.apache.org/repos/asf/camel/trunk/components/camel-spring/src/test/java/org/apache/camel/spring/patterns/FilterTest.java[XML Config].
+[source,java]
+----
+// tag::example[]
+@ContextConfiguration
+public class FilterTest extends SpringRunWithTestSupport {
+
+    @EndpointInject("mock:result")
+    protected MockEndpoint resultEndpoint;
+
+    @Produce("direct:start")
+    protected ProducerTemplate template;
+
+    @DirtiesContext
+    @Test
+    public void testSendMatchingMessage() throws Exception {
+        String expectedBody = "<matched/>";
+
+        resultEndpoint.expectedBodiesReceived(expectedBody);
+
+        template.sendBodyAndHeader(expectedBody, "foo", "bar");
+
+        resultEndpoint.assertIsSatisfied();
+    }
+
+    @DirtiesContext
+    @Test
+    public void testSendNotMatchingMessage() throws Exception {
+        resultEndpoint.expectedMessageCount(0);
+
+        template.sendBodyAndHeader("<notMatched/>", "foo", "notMatchedHeaderValue");
+
+        resultEndpoint.assertIsSatisfied();
+    }
+}
+// end::example[]
+----
+Notice that we use `@DirtiesContext` on the test methods to force Spring Testing to automatically reload the http://camel.apache.org/camelcontext.html[CamelContext] after each test method - this ensures that the tests don't clash with each other, e.g., one test method sending to an endpoint that is then reused in another test method.
+
+Also notice the use of `@ContextConfiguration` to indicate that by default we should look for the file http://svn.apache.org/repos/asf/camel/trunk/components/camel-spring/src/test/resources/org/apache/camel/spring/patterns/FilterTest-context.xml[FilterTest-context.xml on the classpath] to configure the test case. The test context looks like:
+[source,xml]
+----
+<!-- tag::example[] -->
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:context="http://www.springframework.org/schema/context"
+       xsi:schemaLocation="
+       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+       http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
+    ">
+
+  <camelContext xmlns="http://camel.apache.org/schema/spring">
+    <route>
+      <from uri="direct:start"/>
+      <filter>
+        <xpath>$foo = 'bar'</xpath>
+        <to uri="mock:result"/>
+      </filter>
+    </route>
+  </camelContext>
+
+</beans>
+<!-- end::example[] -->
+----
+This test will load a Spring XML configuration file called `FilterTest-context.xml` from the classpath in the same package structure as the `FilterTest` class and initialize it along with any Camel routes we define inside it, then inject the `CamelContext` instance into our test case.
+
+For instance, like this maven folder layout:
+[source,text]
+----
+src/test/java/org/apache/camel/spring/patterns/FilterTest.java
+src/test/resources/org/apache/camel/spring/patterns/FilterTest-context.xml
+----
+
+=== Plain Spring Test Using JUnit 4.x With Java Config Example
+
+You can completely avoid using an XML configuration file by using http://camel.apache.org/spring-java-config.html[Spring Java Config].  Here is a unit test using JUnit 4.x support from Spring Test using http://svn.apache.org/repos/asf/camel/trunk/components/camel-spring-javaconfig/src/test/java/org/apache/camel/spring/javaconfig/patterns/FilterTest.java[Java Config].
+[source,text]
+----
+// tag::example[]
+@RunWith(CamelSpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = {FilterTest.ContextConfig.class}, loader = CamelSpringDelegatingTestContextLoader.class)
+public class FilterTest extends AbstractJUnit4SpringContextTests {
+
+    @EndpointInject("mock:result")
+    protected MockEndpoint resultEndpoint;
+
+    @Produce("direct:start")
+    protected ProducerTemplate template;
+
+    @DirtiesContext
+    @Test
+    public void testSendMatchingMessage() throws Exception {
+        String expectedBody = "<matched/>";
+
+        resultEndpoint.expectedBodiesReceived(expectedBody);
+
+        template.sendBodyAndHeader(expectedBody, "foo", "bar");
+
+        resultEndpoint.assertIsSatisfied();
+    }
+
+    @DirtiesContext
+    @Test
+    public void testSendNotMatchingMessage() throws Exception {
+        resultEndpoint.expectedMessageCount(0);
+
+        template.sendBodyAndHeader("<notMatched/>", "foo", "notMatchedHeaderValue");
+
+        resultEndpoint.assertIsSatisfied();
+    }
+
+    @Configuration
+    public static class ContextConfig extends SingleRouteCamelConfiguration {
+        @Bean
+        public RouteBuilder route() {
+            return new RouteBuilder() {
+                public void configure() {
+                    from("direct:start").filter(header("foo").isEqualTo("bar")).to("mock:result");
+                }
+            };
+        }
+    }
+}
+// end::example[]
+----
+
+This is similar to the XML Config example above except that there is no XML file and instead the nested `ContextConfig` class does all of the configuration; so your entire test case is contained in a single Java class. We currently have to reference by class name this class in the `@ContextConfiguration` which is a bit ugly. Please vote for http://jira.springframework.org/browse/SJC-238[SJC-238] to address this and make Spring Test work more cleanly with Spring JavaConfig.
+
+=== Plain Spring Test Using JUnit 4.0.x Runner With XML Config
+
+You can avoid extending Spring classes by using the `SpringJUnit4ClassRunner` provided by Spring Test.  This custom JUnit runner means you are free to choose your own class hierarchy while retaining all the capabilities of Spring Test.
+
+TIP: This is for Spring 4.0.x. If you use Spring 4.1 or newer, then see the next section.
+
+[source,java]
+----
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration
+public class MyCamelTest {
+    @Autowired
+    protected CamelContext camelContext;
+
+    @EndpointInject("mock:foo")
+    protected MockEndpoint foo;
+
+    @Test
+    @DirtiesContext
+    public void testMocksAreValid() throws Exception {
+        // ...      
+
+        foo.message(0).header("bar").isEqualTo("ABC");
+        MockEndpoint.assertIsSatisfied(camelContext);
+    }
+}
+----
+
+=== Plain Spring Test Using JUnit 4.1.x Runner With XML Config
+
+You can avoid extending Spring classes by using the `SpringJUnit4ClassRunner` provided by Spring Test.  This custom JUnit runner means you are free to choose your own class hierarchy while retaining all the capabilities of Spring Test.
+
+TIP: From *Spring 4.1*, you need to use the `@BootstrapWith` annotation to configure it to use Camel testing, as shown below.
+
+[source,java]
+----
+@RunWith(CamelSpringJUnit4ClassRunner.class)
+@BootstrapWith(CamelTestContextBootstrapper.class)
+@ContextConfiguration
+public class MyCamelTest {
+    @Autowired
+    protected CamelContext camelContext;
+
+    @EndpointInject("mock:foo")
+    protected MockEndpoint foo;
+
+    @Test
+    @DirtiesContext
+    public void testMocksAreValid() throws Exception {
+        // ...      
+
+        foo.message(0).header("bar").isEqualTo("ABC");
+        MockEndpoint.assertIsSatisfied(camelContext);
+    }
+}
+----
+
+[#camel-enhanced-spring-test]
+== Camel Enhanced Spring Test
+
+Using the `org.apache.camel.test.junit4.CamelSpringJUnit4ClassRunner` runner with the `@RunWith` annotation or extending `org.apache.camel.testng.AbstractCamelTestNGSpringContextTests` provides the full feature set of Spring Test with support for the feature set provided in the `CamelTestSupport` classes.
+
+A number of Camel specific annotations have been developed in order to provide for declarative manipulation of the Camel context(s) involved in the test.  These annotations free your test classes from having to inherit from the `CamelSpringTestSupport` classes and also reduce the amount of code required to customize the tests.
+[width="100%",cols="1,1,4,1,1",options="header",]
+|=======================================================================
+|Annotation Class |Applies To |Description |Default Behaviour If Not Present |Default Behavior If Present
+|org.apache.camel.test.spring.DisableJmx a|Class a|
+Indicates if JMX should be globally disabled in the CamelContexts that are bootstrapped  during the test through the use of Spring Test loaded application contexts. a|
+JMX is disabled a|JMX is disabled
+
+|org.apache.camel.test.spring.ExcludeRoutes a|Class a|
+Indicates if certain route builder classes should be excluded from discovery.  Initializes a `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. a|
+Not enabled and no routes are excluded a|No routes are excluded
+
+Indicates if the CamelContexts that are bootstrapped during the test through the use of Spring Test loaded application contexts should use lazy loading of type converters. a|
+Type converters are not lazy loaded a|
+Type converters are not lazy loaded
+
+|org.apache.camel.test.spring.MockEndpoints a|Class a|
+Triggers the auto-mocking of endpoints whose URIs match the provided filter.  The default filter is `"*"` which matches all endpoints.  See `org.apache.camel.impl.InterceptSendToMockEndpointStrategy` for more details on the registration of the mock endpoints. a|
+Not enabled a|All endpoints are sniffed and recorded in a mock endpoint.
+
+|org.apache.camel.test.spring.MockEndpointsAndSkip a|Class a|
+Triggers the auto-mocking of endpoints whose URIs match the provided filter.  The default filter is `"*"`, which matches all endpoints.  See http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/impl/InterceptSendToMockEndpointStrategy.java?view=markup[org.apache.camel.impl.InterceptSendToMockEndpointStrategy] for more details on the registration of the mock endpoints.  This annotation will also skip sending the message to matched endpoints as well. a|
+Not enabled a|All endpoints are sniffed and recorded in a mock endpoint. The original endpoint is not invoked.
+
+|org.apache.camel.test.spring.ProvidesBreakpoint a|Method a|
+Indicates that the annotated method returns an `org.apache.camel.spi.Breakpoint` for use in the test.  Useful for intercepting traffic to all endpoints or simply for setting a break point in an IDE for debugging.  The method must be public, static, take no arguments, and return `org.apache.camel.spi.Breakpoint`. a|
+N/A a|
+The returned `Breakpoint` is registered in the CamelContext(s)
+
+|org.apache.camel.test.spring.ShutdownTimeout a|Class a|
+Indicates to set the shutdown timeout of all CamelContexts 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. a|
+10 seconds a|10 seconds
+
+|org.apache.camel.test.spring.UseAdviceWith a|Class a|
+Indicates the use of `adviceWith()` within the test class.  If a class is annotated with this annotation and `UseAdviceWith#value()` returns true, any CamelContexts 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 `CamelContext#start()` on them at the appropriate time after any advice has been applied to the routes in the CamelContext(s). a|
+CamelContexts do not automatically start. a|CamelContexts do not automatically start.
+
+|org.apache.camel.test.spring.UseOverridePropertiesWithPropertiesComponent a|Method a|
+Indicates that the annotated method returns a `java.util.Properties` for use in the test, and that those properties override any existing properties configured on the `PropertiesComponent`. a|
+a|Override properties
+|=======================================================================
+
+The following example illustrates the use of the `@MockEndpoints` annotation in order to setup mock endpoints as interceptors on all endpoints using the Camel Log component and the `@DisableJmx` annotation to enable JMX which is disabled during tests by default.
+
+TIP: We still use the `@DirtiesContext` annotation to ensure that the CamelContext, routes, and mock endpoints are reinitialized between test methods.
+
+[source,java]
+----
+@RunWith(CamelSpringJUnit4ClassRunner.class)
+@BootstrapWith(CamelTestContextBootstrapper.class)
+@ContextConfiguration
+@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)
+@MockEndpoints("log:*")
+@DisableJmx(false)
+public class CamelSpringJUnit4ClassRunnerPlainTest {
+    @Autowired
+    protected CamelContext camelContext2;
+
+    protected MockEndpoint mockB;
+
+    @EndpointInject(value = "mock:c", context = "camelContext2")
+    protected MockEndpoint mockC;
+
+    @Produce("direct:start2", context = "camelContext2")
+    protected ProducerTemplate start2;
+
+    @EndpointInject(value = "mock:log:org.apache.camel.test.junit4.spring", context = "camelContext2")
+    protected MockEndpoint mockLog;
+
+    @Test
+    public void testPositive() throws Exception {
+        mockC.expectedBodiesReceived("David");
+        mockLog.expectedBodiesReceived("Hello David");
+
+        start2.sendBody("David");
+
+        MockEndpoint.assertIsSatisfied(camelContext);
+    }
+----
+
+
+== Adding More Mock Expectations
+
+If you wish to add any new assertions to your test you can easily do so with the following. Notice how we use `@EndpointInject` to inject a Camel endpoint into our code then the http://camel.apache.org/mock.html[Mock] API to add an expectation on a specific message.
+[source,java]
+----
+@ContextConfiguration
+public class MyCamelTest extends AbstractJUnit38SpringContextTests {
+    @Autowired
+    protected CamelContext camelContext;
+
+    @EndpointInject("mock:foo")
+    protected MockEndpoint foo;
+
+    public void testMocksAreValid() throws Exception {
+        // lets add more expectations
+        foo.message(0).header("bar").isEqualTo("ABC");
+
+        MockEndpoint.assertIsSatisfied(camelContext);
+    }
+}
+----
+
+
+== Further Processing the Received Messages
+
+Sometimes once a http://camel.apache.org/mock.html[Mock] endpoint has received some messages you want to then process them further to add further assertions that your test case worked as you expect.
+
+So you can then process the received message exchanges if you like...
+[source,java]
+----
+@ContextConfiguration
+public class MyCamelTest extends AbstractJUnit38SpringContextTests {
+    @Autowired
+    protected CamelContext camelContext;
+
+    @EndpointInject("mock:foo")
+    protected MockEndpoint foo;
+
+    public void testMocksAreValid() throws Exception {
+        // lets add more expectations...
+
+        MockEndpoint.assertIsSatisfied(camelContext);
+
+        // now lets do some further assertions
+        List<Exchange> list = foo.getReceivedExchanges();
+        for (Exchange exchange : list) {
+            Message in = exchange.getIn();
+            // ...
+        }
+    }
+}
+----
+
+== Sending and Receiving Messages
+
+It might be that the http://camel.apache.org/enterprise-integration-patterns.html[Enterprise Integration Patterns] you have defined in either http://camel.apache.org/spring.html[Spring] XML or using the Java http://camel.apache.org/dsl.html[DSL] do all of the sending and receiving and you might just work with the http://camel.apache.org/mock.html[Mock] endpoints as described above. However sometimes in a test case its useful to explicitly send or receive messages directly.
+
+To send or receive messages you should use the http://camel.apache.org/bean-integration.html[Bean Integration] mechanism. For example to send messages inject a `ProducerTemplate` using the `@EndpointInject` annotation then call the various send methods on this object to send a message to an endpoint. To consume messages use the `@MessageDriven` annotation on a method to have the method invoked when a message is received.
+[source,java]
+----
+public class Foo {
+  @EndpointInject("activemq:foo.bar")
+  ProducerTemplate producer;
+
+  public void doSomething() {
+    // lets send a message!
+    producer.sendBody("<hello>world!</hello>");
+  }
+
+  // lets consume messages from the 'cheese' queue
+  @MessageDriven(uri="activemq:cheese")
+  public void onCheese(String name) {
+    // ...
+  }
+}
+----
+
+
diff --git a/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/CamelAnnotationsHandler.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/CamelAnnotationsHandler.java
new file mode 100644
index 0000000..d28eb14
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/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;
+
+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.junit4.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.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/CamelSpringBootExecutionListener.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/CamelSpringBootExecutionListener.java
new file mode 100644
index 0000000..9b59ba8
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/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;
+
+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("@RunWith(CamelSpringBootRunner.class) 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("@RunWith(CamelSpringBootRunner.class) 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 CamelSpringBootRunner now ready to start CamelContext");
+        CamelAnnotationsHandler.handleCamelContextStartup(context, testClass);
+    }
+
+    @Override
+    public void afterTestMethod(TestContext testContext) throws Exception {
+        LOG.info("@RunWith(CamelSpringBootRunner.class) 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/CamelSpringBootJUnit4ClassRunner.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/CamelSpringBootJUnit4ClassRunner.java
new file mode 100644
index 0000000..e795918
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/CamelSpringBootJUnit4ClassRunner.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.junit.runners.model.InitializationError;
+
+/**
+ * The class {@link CamelSpringBootJUnit4ClassRunner} has been renamed to {@link CamelSpringBootRunner}
+ * which is a shorter and easier to remember name.
+ *
+ * @deprecated use {@link CamelSpringBootRunner}
+ */
+@Deprecated
+public class CamelSpringBootJUnit4ClassRunner extends CamelSpringBootRunner {
+
+    public CamelSpringBootJUnit4ClassRunner(Class<?> clazz) throws InitializationError {
+        super(clazz);
+    }
+}
diff --git a/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/CamelSpringBootRunner.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/CamelSpringBootRunner.java
new file mode 100644
index 0000000..d499bb8
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/CamelSpringBootRunner.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.spring;
+
+import java.util.List;
+
+import org.junit.runners.model.InitializationError;
+import org.springframework.test.context.TestContextManager;
+import org.springframework.test.context.TestExecutionListener;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+/**
+ * An implementation bringing the functionality of {@link CamelSpringTestSupport} to
+ * Spring Boot Test based test cases.  This approach allows developers to implement tests
+ * for their Spring Boot based applications/routes using the typical Spring Test conventions
+ * for test development.
+ */
+public class CamelSpringBootRunner extends SpringJUnit4ClassRunner {
+
+    public CamelSpringBootRunner(Class<?> clazz) throws InitializationError {
+        super(clazz);
+    }
+
+    /**
+     * Returns the specialized manager instance that provides tight integration between Camel testing
+     * features and Spring.
+     *
+     * @return a new instance of {@link CamelTestContextManager}.
+     */
+    @Override
+    protected TestContextManager createTestContextManager(Class<?> clazz) {
+        return new CamelTestContextManager(clazz);
+    }
+
+    /**
+     * An implementation providing additional integration between Spring Test and Camel
+     * testing features.
+     */
+    public static final class CamelTestContextManager extends TestContextManager {
+
+        public CamelTestContextManager(Class<?> testClass) {
+            super(testClass);
+
+            // turn off auto starting spring as we need to do this later
+            System.setProperty("skipStartingCamelContext", "true");
+
+            // is Camel already registered
+            if (!alreadyRegistered()) {
+                // inject Camel first, and then disable jmx and add the stop-watch
+                List<TestExecutionListener> list = getTestExecutionListeners();
+                list.add(0, new CamelSpringTestContextLoaderTestExecutionListener());
+                list.add(1, new DisableJmxTestExecutionListener());
+                list.add(2, new CamelSpringBootExecutionListener());
+                list.add(3, new StopWatchTestExecutionListener());
+            }
+        }
+
+        private boolean alreadyRegistered() {
+            List<TestExecutionListener> list = getTestExecutionListeners();
+            if (list != null) {
+                for (TestExecutionListener listener : list) {
+                    if (listener instanceof CamelSpringTestContextLoaderTestExecutionListener) {
+                        return true;
+                    }
+                }
+            }
+
+            return false;
+        }
+
+    }
+
+}
diff --git a/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/CamelSpringDelegatingTestContextLoader.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/CamelSpringDelegatingTestContextLoader.java
new file mode 100644
index 0000000..3c22382
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/CamelSpringDelegatingTestContextLoader.java
@@ -0,0 +1,138 @@
+/*
+ * 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.lang.reflect.Method;
+
+import org.apache.camel.api.management.JmxSystemPropertyKeys;
+import org.apache.camel.spring.SpringCamelContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.support.BeanDefinitionRegistry;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.context.annotation.AnnotationConfigUtils;
+import org.springframework.test.context.MergedContextConfiguration;
+import org.springframework.test.context.support.DelegatingSmartContextLoader;
+
+/**
+ * CamelSpringDelegatingTestContextLoader which fixes issues in Camel's JavaConfigContextLoader. (adds support for Camel's test annotations)
+ * <br>
+ * <em>This loader can handle either classes or locations for configuring the context.</em>
+ * <br>
+ * NOTE: This TestContextLoader doesn't support the annotation of ExcludeRoutes now.
+ *
+ * @deprecated use {@link CamelSpringRunner} or {@link CamelSpringBootRunner} instead.
+ */
+@Deprecated
+public class CamelSpringDelegatingTestContextLoader extends DelegatingSmartContextLoader {
+
+    protected final Logger logger = LoggerFactory.getLogger(getClass());
+
+    @Override
+    public ApplicationContext loadContext(MergedContextConfiguration mergedConfig) throws Exception {
+        
+        Class<?> testClass = getTestClass();
+        
+        if (logger.isDebugEnabled()) {
+            logger.debug("Loading ApplicationContext for merged context configuration [{}].", mergedConfig);
+        }
+        
+        // Pre CamelContext(s) instantiation setup
+        CamelAnnotationsHandler.handleDisableJmx(null, testClass);
+
+        try {
+            SpringCamelContext.setNoStart(true);
+            System.setProperty("skipStartingCamelContext", "true");
+            ConfigurableApplicationContext context = (ConfigurableApplicationContext) super.loadContext(mergedConfig);
+            SpringCamelContext.setNoStart(false);
+            System.clearProperty("skipStartingCamelContext");
+            return loadContext(context, testClass);
+        } finally {
+            cleanup(testClass);
+        }
+    }
+
+    /**
+     * 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
+     */
+    public ApplicationContext loadContext(ConfigurableApplicationContext context, Class<?> testClass)
+        throws Exception {
+            
+        AnnotationConfigUtils.registerAnnotationConfigProcessors((BeanDefinitionRegistry) context);
+
+        // Post CamelContext(s) instantiation but pre CamelContext(s) start setup
+        CamelAnnotationsHandler.handleRouteCoverage(context, testClass, s -> getTestMethod().getName());
+        CamelAnnotationsHandler.handleProvidesBreakpoint(context, testClass);
+        CamelAnnotationsHandler.handleShutdownTimeout(context, testClass);
+        CamelAnnotationsHandler.handleMockEndpoints(context, testClass);
+        CamelAnnotationsHandler.handleMockEndpointsAndSkip(context, testClass);
+        CamelAnnotationsHandler.handleUseOverridePropertiesWithPropertiesComponent(context, testClass);
+        
+        // CamelContext(s) startup
+        CamelAnnotationsHandler.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());
+            }
+        }
+    }
+
+    /**
+     * 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/CamelSpringJUnit4ClassRunner.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/CamelSpringJUnit4ClassRunner.java
new file mode 100644
index 0000000..5cd2935
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/CamelSpringJUnit4ClassRunner.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.junit.runners.model.InitializationError;
+
+/**
+ * The class {@link CamelSpringJUnit4ClassRunner} has been renamed to {@link CamelSpringRunner}
+ * which is a shorter and easier to remember name.
+ *
+ * @deprecated use {@link CamelSpringRunner}
+ */
+@Deprecated
+public class CamelSpringJUnit4ClassRunner extends CamelSpringRunner {
+
+    public CamelSpringJUnit4ClassRunner(Class<?> clazz) throws InitializationError {
+        super(clazz);
+    }
+}
diff --git a/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/CamelSpringRunner.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/CamelSpringRunner.java
new file mode 100644
index 0000000..9f2569a
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/CamelSpringRunner.java
@@ -0,0 +1,83 @@
+/*
+ * 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.junit.runners.model.InitializationError;
+import org.springframework.test.context.TestContextManager;
+import org.springframework.test.context.TestExecutionListener;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+/**
+ * An implementation bringing the functionality of {@link org.apache.camel.test.spring.CamelSpringTestSupport} to
+ * Spring Test based test cases.  This approach allows developers to implement tests
+ * for their Spring based applications/routes using the typical Spring Test conventions
+ * for test development.
+ */
+public class CamelSpringRunner extends SpringJUnit4ClassRunner {
+
+    public CamelSpringRunner(Class<?> clazz) throws InitializationError {
+        super(clazz);
+    }
+
+    /**
+     * Returns the specialized manager instance that provides tight integration between Camel testing
+     * features and Spring.
+     *
+     * @return a new instance of {@link CamelTestContextManager}.
+     */
+    @Override
+    protected TestContextManager createTestContextManager(Class<?> clazz) {
+        return new CamelTestContextManager(clazz);
+    }
+
+    /**
+     * An implementation providing additional integration between Spring Test and Camel
+     * testing features.
+     */
+    public static final class CamelTestContextManager extends TestContextManager {
+
+        public CamelTestContextManager(Class<?> testClass) {
+            super(testClass);
+
+            // is Camel already registered
+            if (!alreadyRegistered()) {
+                // inject Camel first, and then disable jmx and add the stop-watch
+                List<TestExecutionListener> list = getTestExecutionListeners();
+                list.add(0, new CamelSpringTestContextLoaderTestExecutionListener());
+                list.add(1, new DisableJmxTestExecutionListener());
+                list.add(2, new StopWatchTestExecutionListener());
+            }
+        }
+
+        private boolean alreadyRegistered() {
+            List<TestExecutionListener> list = getTestExecutionListeners();
+            if (list != null) {
+                for (TestExecutionListener listener : list) {
+                    if (listener instanceof CamelSpringTestContextLoaderTestExecutionListener) {
+                        return true;
+                    }
+                }
+            }
+
+            return false;
+        }
+
+    }
+
+}
diff --git a/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/CamelSpringTestContextLoader.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/CamelSpringTestContextLoader.java
new file mode 100644
index 0000000..df4d626
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/CamelSpringTestContextLoader.java
@@ -0,0 +1,551 @@
+/*
+ * 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.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.junit4.CamelTestSupport;
+import org.apache.camel.test.spring.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.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)) {
+            // route coverage need JMX so do not disable it by default
+            LOG.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
+     */
+    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/CamelSpringTestContextLoaderTestExecutionListener.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/CamelSpringTestContextLoaderTestExecutionListener.java
new file mode 100644
index 0000000..8bd41f6
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/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;
+
+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/CamelSpringTestHelper.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/CamelSpringTestHelper.java
new file mode 100644
index 0000000..7242054
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/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;
+
+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/CamelSpringTestSupport.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/CamelSpringTestSupport.java
new file mode 100644
index 0000000..4e8ff41
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/CamelSpringTestSupport.java
@@ -0,0 +1,211 @@
+/*
+ * 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.Arrays;
+import java.util.HashSet;
+import java.util.List;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.ExtendedCamelContext;
+import org.apache.camel.spring.SpringCamelContext;
+import org.apache.camel.test.ExcludingPackageScanClassResolver;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.apache.camel.util.IOHelper;
+import org.apache.camel.util.ObjectHelper;
+import org.junit.After;
+import org.springframework.beans.factory.support.RootBeanDefinition;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.AbstractApplicationContext;
+import org.springframework.context.support.GenericApplicationContext;
+
+/**
+ * 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();
+    
+    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("Should have created a valid Spring application context", 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
+    @After
+    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("No spring bean found for name <" + name + ">", value);
+        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/CamelTestContextBootstrapper.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/CamelTestContextBootstrapper.java
new file mode 100644
index 0000000..192d2d3
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/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;
+
+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/DisableJmx.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/DisableJmx.java
new file mode 100644
index 0000000..0117544
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/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;
+
+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/DisableJmxTestExecutionListener.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/DisableJmxTestExecutionListener.java
new file mode 100644
index 0000000..cc04c96
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/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;
+
+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/EnableRouteCoverage.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/EnableRouteCoverage.java
new file mode 100644
index 0000000..a6e9c00
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/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;
+
+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/ExcludeRoutes.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/ExcludeRoutes.java
new file mode 100644
index 0000000..d1315c5
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/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;
+
+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/MockEndpoints.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/MockEndpoints.java
new file mode 100644
index 0000000..3eff4ce
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/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;
+
+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/MockEndpointsAndSkip.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/MockEndpointsAndSkip.java
new file mode 100644
index 0000000..dc09818
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/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;
+
+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/ProvidesBreakpoint.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/ProvidesBreakpoint.java
new file mode 100644
index 0000000..19a6fdc
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/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;
+
+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/RouteCoverageDumper.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/RouteCoverageDumper.java
new file mode 100644
index 0000000..be8a29e
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/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;
+
+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/RouteCoverageEventNotifier.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/RouteCoverageEventNotifier.java
new file mode 100644
index 0000000..55474fa
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/RouteCoverageEventNotifier.java
@@ -0,0 +1,51 @@
+/*
+ * 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.function.Function;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.spi.CamelEvent;
+import org.apache.camel.spi.CamelEvent.CamelContextEvent;
+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/ShutdownTimeout.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/ShutdownTimeout.java
new file mode 100644
index 0000000..2c3ac6c
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/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;
+
+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/StopWatchTestExecutionListener.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/StopWatchTestExecutionListener.java
new file mode 100644
index 0000000..f9e3585
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/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;
+
+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.junit4.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/UseAdviceWith.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/UseAdviceWith.java
new file mode 100644
index 0000000..a114705
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/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;
+
+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/UseOverridePropertiesWithPropertiesComponent.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/UseOverridePropertiesWithPropertiesComponent.java
new file mode 100644
index 0000000..0051181
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/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;
+
+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..1456d1d
--- /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.CamelSpringTestSupport;
+import org.junit.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..eeae215
--- /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.CamelSpringTestSupport;
+import org.junit.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..a9c7007
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/issues/AdviceWithOnExceptionMultipleIssueTest.java
@@ -0,0 +1,117 @@
+/*
+ * 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.CamelSpringTestSupport;
+import org.junit.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..b2dcbff
--- /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.CamelSpringTestSupport;
+import org.junit.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..ccac96f
--- /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() throws Exception {
+        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..72e841a
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/patterns/DebugSpringTest.java
@@ -0,0 +1,81 @@
+/*
+ * 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.CamelSpringTestSupport;
+import org.junit.Test;
+import org.springframework.context.support.AbstractApplicationContext;
+import org.springframework.context.support.GenericApplicationContext;
+
+public class DebugSpringTest extends CamelSpringTestSupport {
+    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("The debugger is not called!", debugged);
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        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..c692033
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/patterns/MyProduceBean.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.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..0319c98
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/patterns/MySender.java
@@ -0,0 +1,25 @@
+/*
+ * 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..dc1b762
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/patterns/ProduceBeanTest.java
@@ -0,0 +1,42 @@
+/*
+ * 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.CamelSpringTestSupport;
+import org.junit.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..298378c
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/patterns/ProducerBeanInjectTest.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.junit.Assert;
+import org.junit.Test;
+import org.springframework.context.support.AbstractApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+public class ProducerBeanInjectTest extends Assert {
+
+    @Test
+    public void checkProducerBeanInjection() {
+        AbstractApplicationContext applicationContext = createApplicationContext();
+        MyProduceBean bean = applicationContext.getBean("myProduceBean", MyProduceBean.class);
+        assertNotNull("The producerTemplate should not be null.", bean.getProducerTemplate());
+        assertEquals("Get a wrong response", "Camel rocks!", bean.getProducerTemplate().requestBody("Camel"));
+    }
+
+    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..c257e68
--- /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.CamelSpringTestSupport;
+import org.junit.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..8ef9de6
--- /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.junit.Test;
+import org.junit.runner.RunWith;
+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")
+@RunWith(CamelSpringRunner.class)
+public class CamelSpringActiveProfileTest {
+
+    @Autowired
+    protected CamelContext camelContext;
+
+    @Produce(value = "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/CamelSpringOverridePropertiesForPropertyInjectTest.java b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringOverridePropertiesForPropertyInjectTest.java
new file mode 100644
index 0000000..493e9a8
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringOverridePropertiesForPropertyInjectTest.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 java.util.Properties;
+
+import org.apache.camel.Produce;
+import org.apache.camel.ProducerTemplate;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.BootstrapWith;
+import org.springframework.test.context.ContextConfiguration;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+@RunWith(CamelSpringRunner.class)
+@BootstrapWith(CamelTestContextBootstrapper.class)
+@ContextConfiguration()
+@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
+public class CamelSpringOverridePropertiesForPropertyInjectTest {
+    
+    private static final String EXPECTED_PROPERTY_VALUE = "The value is overriden";
+    
+    @Produce(uri = "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() throws Exception {
+        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..d28e2dd
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringOverridePropertiesTest.java
@@ -0,0 +1,72 @@
+/*
+ * 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.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.BootstrapWith;
+import org.springframework.test.context.ContextConfiguration;
+
+@RunWith(CamelSpringRunner.class)
+@BootstrapWith(CamelTestContextBootstrapper.class)
+@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/CamelSpringPropertiesLocationElementTest.java b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringPropertiesLocationElementTest.java
new file mode 100644
index 0000000..13389e5
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringPropertiesLocationElementTest.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 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.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.BootstrapWith;
+import org.springframework.test.context.ContextConfiguration;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+@RunWith(CamelSpringRunner.class)
+@BootstrapWith(CamelTestContextBootstrapper.class)
+@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("Properties component not defined", pc);
+
+        List<String> locations = pc.getLocations();
+
+        assertNotNull(locations);
+        assertEquals("Properties locations", 4, locations.size());
+
+        producer.sendBody("direct:start", null);
+
+        mock.assertIsSatisfied();
+    }
+}
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..bb0c79b
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringRouteProcessorDumpRouteCoverageTest.java
@@ -0,0 +1,55 @@
+/*
+ * 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.junit4.TestSupport;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+@EnableRouteCoverage
+public class CamelSpringRouteProcessorDumpRouteCoverageTest extends CamelSpringRunnerPlainTest {
+
+    @BeforeClass
+    public static void prepareFiles() throws Exception {
+        TestSupport.deleteDirectory("target/camel-route-coverage");
+    }
+
+    @Override
+    @Test
+    public void testJmx() throws Exception {
+        // JMX is enabled with route coverage
+        assertEquals(JmxManagementStrategy.class, camelContext.getManagementStrategy().getClass());
+    }
+
+    @Override
+    public void testRouteCoverage() throws Exception {
+        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/CamelSpringRunnerDisableJmxInheritedOverrideTest.java b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringRunnerDisableJmxInheritedOverrideTest.java
new file mode 100644
index 0000000..e53e8e9
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringRunnerDisableJmxInheritedOverrideTest.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.impl.engine.DefaultManagementStrategy;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+@DisableJmx
+public class CamelSpringRunnerDisableJmxInheritedOverrideTest
+        extends CamelSpringRunnerDisableJmxTest {
+
+    @Override
+    @Test
+    public void testJmx() throws Exception {
+        assertEquals(DefaultManagementStrategy.class, camelContext.getManagementStrategy().getClass());
+    }
+}
diff --git a/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringRunnerDisableJmxInheritedTest.java b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringRunnerDisableJmxInheritedTest.java
new file mode 100644
index 0000000..472e1f5
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringRunnerDisableJmxInheritedTest.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 CamelSpringRunnerDisableJmxInheritedTest
+        extends CamelSpringRunnerDisableJmxTest {
+}
diff --git a/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringRunnerDisableJmxTest.java b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringRunnerDisableJmxTest.java
new file mode 100644
index 0000000..937e050
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringRunnerDisableJmxTest.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.management.JmxManagementStrategy;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+@DisableJmx(false)
+public class CamelSpringRunnerDisableJmxTest
+        extends CamelSpringRunnerPlainTest {
+
+    @Test
+    @Override
+    public void testJmx() throws Exception {
+        assertEquals(JmxManagementStrategy.class, camelContext.getManagementStrategy().getClass());
+    }
+}
diff --git a/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringRunnerExcludeRoutesTest.java b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringRunnerExcludeRoutesTest.java
new file mode 100644
index 0000000..3244a60
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringRunnerExcludeRoutesTest.java
@@ -0,0 +1,32 @@
+/*
+ * 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.junit.Test;
+
+import static org.junit.Assert.assertNull;
+
+@ExcludeRoutes(TestRouteBuilder.class)
+public class CamelSpringRunnerExcludeRoutesTest
+        extends CamelSpringRunnerPlainTest {
+
+    @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/CamelSpringRunnerPlainTest.java b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringRunnerPlainTest.java
new file mode 100644
index 0000000..f5d0fb6
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringRunnerPlainTest.java
@@ -0,0 +1,113 @@
+/*
+ * 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.util.StopWatch;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+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.BootstrapWith;
+import org.springframework.test.context.ContextConfiguration;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+// tag::example[]
+@RunWith(CamelSpringRunner.class)
+// must tell Spring to bootstrap with Camel
+@BootstrapWith(CamelTestContextBootstrapper.class)
+@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 CamelSpringRunnerPlainTest {
+    
+    @Autowired
+    protected CamelContext camelContext;
+    
+    @EndpointInject(value = "mock:a")
+    protected MockEndpoint mockA;
+    
+    @EndpointInject(value = "mock:b")
+    protected MockEndpoint mockB;
+    
+    @Produce(value = "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() throws Exception {
+        assertEquals(DefaultManagementStrategy.class, camelContext.getManagementStrategy().getClass());
+    }
+    
+    @Test
+    public void testShutdownTimeout() throws Exception {
+        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() throws Exception {
+        // noop
+    }
+
+}
+// end::example[]
+
diff --git a/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringRunnerProvidesBreakpointInherritedTest.java b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringRunnerProvidesBreakpointInherritedTest.java
new file mode 100644
index 0000000..00b8058
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringRunnerProvidesBreakpointInherritedTest.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 CamelSpringRunnerProvidesBreakpointInherritedTest
+        extends CamelSpringRunnerProvidesBreakpointTest {
+
+}
diff --git a/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringRunnerProvidesBreakpointTest.java b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringRunnerProvidesBreakpointTest.java
new file mode 100644
index 0000000..3a89e1e
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringRunnerProvidesBreakpointTest.java
@@ -0,0 +1,66 @@
+/*
+ * 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.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+public class CamelSpringRunnerProvidesBreakpointTest
+        extends CamelSpringRunnerPlainTest {
+
+    @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/CamelSpringRunnerShutdownTimeoutInheritedOverrideTest.java b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringRunnerShutdownTimeoutInheritedOverrideTest.java
new file mode 100644
index 0000000..0d19466
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringRunnerShutdownTimeoutInheritedOverrideTest.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 java.util.concurrent.TimeUnit;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+@ShutdownTimeout
+public class CamelSpringRunnerShutdownTimeoutInheritedOverrideTest
+        extends CamelSpringRunnerShutdownTimeoutTest {
+
+    @Test
+    @Override
+    public void testShutdownTimeout() throws Exception {
+        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/CamelSpringRunnerShutdownTimeoutInheritedTest.java b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringRunnerShutdownTimeoutInheritedTest.java
new file mode 100644
index 0000000..d3ae14f
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringRunnerShutdownTimeoutInheritedTest.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 CamelSpringRunnerShutdownTimeoutInheritedTest
+        extends CamelSpringRunnerShutdownTimeoutTest {
+
+}
diff --git a/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringRunnerShutdownTimeoutTest.java b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringRunnerShutdownTimeoutTest.java
new file mode 100644
index 0000000..3b33cb7
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringRunnerShutdownTimeoutTest.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 java.util.concurrent.TimeUnit;
+
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+@ShutdownTimeout(value = 11, timeUnit = TimeUnit.MILLISECONDS)
+public class CamelSpringRunnerShutdownTimeoutTest
+        extends CamelSpringRunnerPlainTest {
+
+    @Test
+    @Override
+    public void testShutdownTimeout() throws Exception {
+        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/CamelSpringRunnerTestPropertySourceTest.java b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringRunnerTestPropertySourceTest.java
new file mode 100644
index 0000000..576a4d6
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringRunnerTestPropertySourceTest.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;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Produce;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.test.context.BootstrapWith;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.TestPropertySource;
+
+@RunWith(CamelSpringRunner.class)
+@BootstrapWith(CamelTestContextBootstrapper.class)
+@ContextConfiguration
+@TestPropertySource(properties = "fixedBody=Camel")
+public class CamelSpringRunnerTestPropertySourceTest {
+
+    @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/CamelSpringRunnerUseAdviceWithTest.java b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringRunnerUseAdviceWithTest.java
new file mode 100644
index 0000000..a826b8a
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringRunnerUseAdviceWithTest.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;
+
+import org.apache.camel.ServiceStatus;
+import org.apache.camel.util.StopWatch;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+@UseAdviceWith
+public class CamelSpringRunnerUseAdviceWithTest extends CamelSpringRunnerPlainTest {
+    
+    @Before
+    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, but was: " + taken, taken > 0);
+        assertTrue(taken + " < 3000, but was: " + taken, taken < 3000);
+    }
+}
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..29a4e77
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/CamelSpringTestSupportActiveProfileTest.java
@@ -0,0 +1,51 @@
+/*
+ * 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.junit.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/TestPropertyInjectRouteBuilder.java b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/TestPropertyInjectRouteBuilder.java
new file mode 100644
index 0000000..62db815
--- /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() throws Exception {
+        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..62564c4
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/TestRouteBuilder.java
@@ -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.
+ */
+package org.apache.camel.test.spring;
+
+import org.apache.camel.builder.RouteBuilder;
+
+public class TestRouteBuilder extends RouteBuilder {
+
+    @Override
+    public void configure() throws Exception {
+        
+        from("direct:z")
+            .routeId("excludedRoute")
+            .to("log:org.apache.camel.test.junit4.spring");
+    }
+}
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/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/CamelSpringRunnerPlainTest-context.xml b/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/spring/CamelSpringRunnerPlainTest-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/CamelSpringRunnerPlainTest-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/CamelSpringRunnerTestPropertySourceTest-context.xml b/components/camel-test-spring-junit5/src/test/resources/org/apache/camel/test/spring/CamelSpringRunnerTestPropertySourceTest-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/CamelSpringRunnerTestPropertySourceTest-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/parent/pom.xml b/parent/pom.xml
index a483ce0..33decc2 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -2247,6 +2247,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 1fba710..5271498 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
@@ -3135,6 +3135,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>