You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by al...@apache.org on 2019/09/24 16:22:39 UTC

[camel] 01/01: CAMEL-13965: Added the @CamelSpringBootTest annotation

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 385a3d023c3c125998a1b21b7302d2de8fce9224
Author: aldettinger <al...@gmail.com>
AuthorDate: Tue Sep 24 18:21:45 2019 +0200

    CAMEL-13965: Added the @CamelSpringBootTest annotation
---
 components/camel-spring-boot/pom.xml               |  7 +--
 .../src/main/docs/spring-boot.adoc                 | 52 ++++++++++++++++++++-
 .../MyApplicationTest.java}                        | 39 +++++++---------
 .../apache/camel/spring/boot/example/MyRoute.java  | 30 ++++++++++++
 .../spring/boot/issues/StreamCachingTest.java      |  4 +-
 .../spring/boot/mockendpoints/AdviceWithTest.java  | 11 ++---
 .../MockEndpointsAndSkipDirtiesContextTest.java    |  9 ++--
 .../boot/mockendpoints/MockEndpointsTest.java      |  9 ++--
 .../camel/spring/boot/routefilter/BarTest.java     | 10 ++--
 .../routefilter/FooExcludeRouteAnnotationTest.java |  9 ++--
 .../camel/spring/boot/routefilter/FooTest.java     |  7 ++-
 .../src/main/docs/test-spring-junit5.adoc          |  1 +
 .../junit5/CamelSpringBootExecutionListener.java   | 24 ++++++++--
 ...utionListener.java => CamelSpringBootTest.java} | 32 ++++++-------
 ...ringTestContextLoaderTestExecutionListener.java | 23 +++++----
 .../junit5/DisableJmxTestExecutionListener.java    | 15 +++++-
 .../junit5/SpringTestExecutionListenerSorter.java  | 47 +++++++++++++++++++
 .../junit5/StopWatchTestExecutionListener.java     | 17 ++++++-
 .../SpringTestExecutionListenerSorterTest.java     | 54 ++++++++++++++++++++++
 19 files changed, 300 insertions(+), 100 deletions(-)

diff --git a/components/camel-spring-boot/pom.xml b/components/camel-spring-boot/pom.xml
index ee22f30..90b573f 100644
--- a/components/camel-spring-boot/pom.xml
+++ b/components/camel-spring-boot/pom.xml
@@ -102,7 +102,7 @@
         <!-- Testing dependencies -->
         <dependency>
             <groupId>org.apache.camel</groupId>
-            <artifactId>camel-test-spring</artifactId>
+            <artifactId>camel-test-spring-junit5</artifactId>
             <scope>test</scope>
         </dependency>
         <dependency>
@@ -111,11 +111,6 @@
             <scope>test</scope>
         </dependency>
         <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
             <groupId>org.awaitility</groupId>
             <artifactId>awaitility</artifactId>
             <scope>test</scope>
diff --git a/components/camel-spring-boot/src/main/docs/spring-boot.adoc b/components/camel-spring-boot/src/main/docs/spring-boot.adoc
index 05fcc26..bf247f9 100644
--- a/components/camel-spring-boot/src/main/docs/spring-boot.adoc
+++ b/components/camel-spring-boot/src/main/docs/spring-boot.adoc
@@ -577,7 +577,7 @@ The Rest-DSL XML files should be Camel XML rests (not CamelContext) such as
 ----
 
 [[SpringBoot-Testing]]
-== Testing
+== Testing the JUnit 4 way
 For testing, Maven users will need to add the following dependencies to their `pom.xml`:
 
 [source,xml]
@@ -627,3 +627,53 @@ public class MyApplicationTest {
 
 }
 ----
+== Testing the JUnit 5 way
+For testing, Maven users will need to add the following dependencies to their `pom.xml`:
+
+[source,xml]
+----
+<dependency>
+    <groupId>org.springframework.boot</groupId>
+    <artifactId>spring-boot-starter-test</artifactId>
+    <version>${spring-boot.version}</version> <!-- Use the same version as your Spring Boot version -->
+    <scope>test</scope>
+</dependency>
+<dependency>
+    <groupId>org.apache.camel</groupId>
+    <artifactId>camel-test-spring-junit5</artifactId>
+    <version>${camel.version}</version> <!-- use the same version as your Camel core version -->
+    <scope>test</scope>
+</dependency>
+----
+
+To test a Camel Spring Boot application, annotate your test class(es) with
+`@CamelSpringBootTest`. This brings Camel's Spring Test
+support to your application, so that you can write tests using
+https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html[Spring Boot test conventions].
+
+To get the `CamelContext` or `ProducerTemplate`, you can inject them into the class in the normal Spring manner, using `@Autowired`.
+
+You can also use xref:manual::spring-testing.adoc[Camel Spring test annotations] to configure tests declaratively. This example uses the `@MockEndpoints` annotation to auto-mock an endpoint:
+
+[source,java]
+----
+@CamelSpringBootTest
+@SpringBootApplication
+@MockEndpoints("direct:end")
+public class MyApplicationTest {
+
+    @Autowired
+    private ProducerTemplate template;
+
+    @EndpointInject("mock:direct:end")
+    private MockEndpoint mock;
+
+    @Test
+    public void testReceive() throws Exception {
+        mock.expectedBodiesReceived("Hello");
+        template.sendBody("direct:start", "Hello");
+        mock.assertIsSatisfied();
+    }
+
+}
+----
diff --git a/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/routefilter/BarTest.java b/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/example/MyApplicationTest.java
similarity index 57%
copy from components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/routefilter/BarTest.java
copy to components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/example/MyApplicationTest.java
index f563e8a..720f30a 100644
--- a/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/routefilter/BarTest.java
+++ b/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/example/MyApplicationTest.java
@@ -14,40 +14,35 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.spring.boot.routefilter;
+package org.apache.camel.spring.boot.example;
 
+import org.apache.camel.EndpointInject;
 import org.apache.camel.ProducerTemplate;
 import org.apache.camel.component.mock.MockEndpoint;
-import org.apache.camel.model.ModelCamelContext;
-import org.apache.camel.test.spring.CamelSpringBootRunner;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+import org.apache.camel.test.spring.junit5.MockEndpoints;
+import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.boot.test.context.SpringBootTest;
 
-@RunWith(CamelSpringBootRunner.class)
+/**
+ * This example is included in the spring-boot.adoc "Testing the JUnit 5 way".
+ */
+@CamelSpringBootTest
 @SpringBootApplication
-@SpringBootTest(classes = BarTest.class,
-    properties = {"camel.springboot.java-routes-include-pattern=**/Bar*"})
-public class BarTest {
+@MockEndpoints("direct:end")
+public class MyApplicationTest {
 
     @Autowired
-    ProducerTemplate producerTemplate;
+    private ProducerTemplate template;
 
-    @Autowired
-    ModelCamelContext camelContext;
+    @EndpointInject("mock:direct:end")
+    private MockEndpoint mock;
 
     @Test
-    public void shouldSendToBar() throws Exception {
-        // Given
-        MockEndpoint mock = camelContext.getEndpoint("mock:bar", MockEndpoint.class);
-        mock.expectedBodiesReceived("Hello Bar");
-
-        // When
-        producerTemplate.sendBody("direct:start", "Hello Bar");
-
-        // Then
+    public void testReceive() throws Exception {
+        mock.expectedBodiesReceived("Hello");
+        template.sendBody("direct:start", "Hello");
         mock.assertIsSatisfied();
     }
 
diff --git a/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/example/MyRoute.java b/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/example/MyRoute.java
new file mode 100644
index 0000000..e48c401
--- /dev/null
+++ b/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/example/MyRoute.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.spring.boot.example;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.springframework.stereotype.Component;
+
+@Component
+public class MyRoute extends RouteBuilder {
+
+    @Override
+    public void configure() throws Exception {
+        from("direct:start").to("direct:end");
+        from("direct:end").log("done");
+    }
+}
diff --git a/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/issues/StreamCachingTest.java b/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/issues/StreamCachingTest.java
index 75dcaeb..8bf15ba 100644
--- a/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/issues/StreamCachingTest.java
+++ b/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/issues/StreamCachingTest.java
@@ -27,8 +27,8 @@ import org.apache.camel.EndpointInject;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.mock.MockEndpoint;
 import org.apache.camel.spring.boot.SpringTypeConverter;
-import org.apache.camel.test.junit4.CamelTestSupport;
-import org.junit.Test;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.junit.jupiter.api.Test;
 import org.springframework.core.convert.ConversionService;
 import org.springframework.core.convert.support.DefaultConversionService;
 
diff --git a/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/mockendpoints/AdviceWithTest.java b/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/mockendpoints/AdviceWithTest.java
index bea0229..1b02b1b 100644
--- a/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/mockendpoints/AdviceWithTest.java
+++ b/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/mockendpoints/AdviceWithTest.java
@@ -21,17 +21,16 @@ import org.apache.camel.builder.AdviceWithRouteBuilder;
 import org.apache.camel.component.mock.MockEndpoint;
 import org.apache.camel.model.ModelCamelContext;
 import org.apache.camel.reifier.RouteReifier;
-import org.apache.camel.test.spring.CamelSpringBootRunner;
-import org.apache.camel.test.spring.UseAdviceWith;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+import org.apache.camel.test.spring.junit5.UseAdviceWith;
+import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.boot.test.context.SpringBootTest;
 
-import static org.junit.Assert.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertFalse;
 
-@RunWith(CamelSpringBootRunner.class)
+@CamelSpringBootTest
 @UseAdviceWith
 @SpringBootApplication
 @SpringBootTest(classes = AdviceWithTest.class)
diff --git a/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/mockendpoints/MockEndpointsAndSkipDirtiesContextTest.java b/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/mockendpoints/MockEndpointsAndSkipDirtiesContextTest.java
index 6133451..0a8f17e 100644
--- a/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/mockendpoints/MockEndpointsAndSkipDirtiesContextTest.java
+++ b/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/mockendpoints/MockEndpointsAndSkipDirtiesContextTest.java
@@ -22,17 +22,16 @@ import org.apache.camel.Produce;
 import org.apache.camel.ProducerTemplate;
 import org.apache.camel.component.mock.MockEndpoint;
 import org.apache.camel.spring.SpringRouteBuilder;
-import org.apache.camel.test.spring.CamelSpringBootRunner;
-import org.apache.camel.test.spring.MockEndpointsAndSkip;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+import org.apache.camel.test.spring.junit5.MockEndpointsAndSkip;
+import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.test.annotation.DirtiesContext;
 
-@RunWith(CamelSpringBootRunner.class)
+@CamelSpringBootTest
 @MockEndpointsAndSkip("direct:b")
 @SpringBootApplication
 @SpringBootTest(classes = MockEndpointsAndSkipDirtiesContextTest.class)
diff --git a/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/mockendpoints/MockEndpointsTest.java b/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/mockendpoints/MockEndpointsTest.java
index bacfc31..3573dfb 100644
--- a/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/mockendpoints/MockEndpointsTest.java
+++ b/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/mockendpoints/MockEndpointsTest.java
@@ -19,15 +19,14 @@ package org.apache.camel.spring.boot.mockendpoints;
 import org.apache.camel.CamelContext;
 import org.apache.camel.FluentProducerTemplate;
 import org.apache.camel.component.mock.MockEndpoint;
-import org.apache.camel.test.spring.CamelSpringBootRunner;
-import org.apache.camel.test.spring.MockEndpoints;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+import org.apache.camel.test.spring.junit5.MockEndpoints;
+import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.boot.test.context.SpringBootTest;
 
-@RunWith(CamelSpringBootRunner.class)
+@CamelSpringBootTest
 @MockEndpoints
 @SpringBootApplication
 @SpringBootTest(classes = MockEndpointsTest.class)
diff --git a/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/routefilter/BarTest.java b/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/routefilter/BarTest.java
index f563e8a..396e087 100644
--- a/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/routefilter/BarTest.java
+++ b/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/routefilter/BarTest.java
@@ -19,17 +19,15 @@ package org.apache.camel.spring.boot.routefilter;
 import org.apache.camel.ProducerTemplate;
 import org.apache.camel.component.mock.MockEndpoint;
 import org.apache.camel.model.ModelCamelContext;
-import org.apache.camel.test.spring.CamelSpringBootRunner;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.boot.test.context.SpringBootTest;
 
-@RunWith(CamelSpringBootRunner.class)
+@CamelSpringBootTest
 @SpringBootApplication
-@SpringBootTest(classes = BarTest.class,
-    properties = {"camel.springboot.java-routes-include-pattern=**/Bar*"})
+@SpringBootTest(classes = BarTest.class, properties = {"camel.springboot.java-routes-include-pattern=**/Bar*"})
 public class BarTest {
 
     @Autowired
diff --git a/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/routefilter/FooExcludeRouteAnnotationTest.java b/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/routefilter/FooExcludeRouteAnnotationTest.java
index badc9a4..281792b 100644
--- a/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/routefilter/FooExcludeRouteAnnotationTest.java
+++ b/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/routefilter/FooExcludeRouteAnnotationTest.java
@@ -19,15 +19,14 @@ package org.apache.camel.spring.boot.routefilter;
 import org.apache.camel.ProducerTemplate;
 import org.apache.camel.component.mock.MockEndpoint;
 import org.apache.camel.model.ModelCamelContext;
-import org.apache.camel.test.spring.CamelSpringBootRunner;
-import org.apache.camel.test.spring.ExcludeRoutes;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+import org.apache.camel.test.spring.junit5.ExcludeRoutes;
+import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.boot.test.context.SpringBootTest;
 
-@RunWith(CamelSpringBootRunner.class)
+@CamelSpringBootTest
 @SpringBootApplication()
 @SpringBootTest(classes = FooTest.class)
 @ExcludeRoutes({BarRoute.class, DrinkRoute.class})
diff --git a/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/routefilter/FooTest.java b/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/routefilter/FooTest.java
index f12b309..66a3ff4 100644
--- a/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/routefilter/FooTest.java
+++ b/components/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/routefilter/FooTest.java
@@ -19,14 +19,13 @@ package org.apache.camel.spring.boot.routefilter;
 import org.apache.camel.ProducerTemplate;
 import org.apache.camel.component.mock.MockEndpoint;
 import org.apache.camel.model.ModelCamelContext;
-import org.apache.camel.test.spring.CamelSpringBootRunner;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.boot.test.context.SpringBootTest;
 
-@RunWith(CamelSpringBootRunner.class)
+@CamelSpringBootTest
 @SpringBootApplication()
 @SpringBootTest(classes = FooTest.class,
     properties = {"camel.springboot.java-routes-exclude-pattern=**/Bar*,**/Drink*"})
diff --git a/components/camel-test-spring-junit5/src/main/docs/test-spring-junit5.adoc b/components/camel-test-spring-junit5/src/main/docs/test-spring-junit5.adoc
index 58717f0..31b233f 100644
--- a/components/camel-test-spring-junit5/src/main/docs/test-spring-junit5.adoc
+++ b/components/camel-test-spring-junit5/src/main/docs/test-spring-junit5.adoc
@@ -138,3 +138,4 @@ Tips: It's possible to run JUnit 4 & JUnit 5 based Camel Spring tests side by si
 * Imports of `org.apache.camel.test.spring.\*` should be replaced with `org.apache.camel.test.spring.junit5.*`
 * Usage of `@RunWith(CamelSpringRunner.class)` should be replaced with `@CamelSpringTest`
 * Usage of `@BootstrapWith(CamelTestContextBootstrapper.class)` should be replaced with `@CamelSpringTest`
+* Usage of `@RunWith(CamelSpringBootRunner.class)` should be replaced with `@CamelSpringBootTest`
diff --git a/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/CamelSpringBootExecutionListener.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/CamelSpringBootExecutionListener.java
index 41deaf7..898f058 100644
--- a/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/CamelSpringBootExecutionListener.java
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/CamelSpringBootExecutionListener.java
@@ -29,6 +29,17 @@ public class CamelSpringBootExecutionListener extends AbstractTestExecutionListe
 
     private static final Logger LOG = LoggerFactory.getLogger(CamelSpringBootExecutionListener.class);
 
+    /**
+     * Returns the precedence that is used by Spring to choose the appropriate
+     * execution order of test listeners.
+     * 
+     * See {@link SpringTestExecutionListenerSorter#getPrecedence(Class)} for more.
+     */
+    @Override
+    public int getOrder() {
+        return SpringTestExecutionListenerSorter.getPrecedence(getClass());
+    }
+
     @Override
     public void prepareTestInstance(TestContext testContext) throws Exception {
         LOG.info("CamelSpringBootExecutionListener preparing: {}", testContext.getTestClass());
@@ -45,9 +56,10 @@ public class CamelSpringBootExecutionListener extends AbstractTestExecutionListe
         // not to start it just yet
         SpringCamelContext.setNoStart(true);
         System.setProperty("skipStartingCamelContext", "true");
-        ConfigurableApplicationContext context = (ConfigurableApplicationContext) testContext.getApplicationContext();
+        ConfigurableApplicationContext context = (ConfigurableApplicationContext)testContext.getApplicationContext();
 
-        // Post CamelContext(s) instantiation but pre CamelContext(s) start setup
+        // Post CamelContext(s) instantiation but pre CamelContext(s) start
+        // setup
         CamelAnnotationsHandler.handleProvidesBreakpoint(context, testClass);
         CamelAnnotationsHandler.handleShutdownTimeout(context, testClass);
         CamelAnnotationsHandler.handleMockEndpoints(context, testClass);
@@ -65,7 +77,7 @@ public class CamelSpringBootExecutionListener extends AbstractTestExecutionListe
         Class<?> testClass = testContext.getTestClass();
         String testName = testContext.getTestMethod().getName();
 
-        ConfigurableApplicationContext context = (ConfigurableApplicationContext) testContext.getApplicationContext();
+        ConfigurableApplicationContext context = (ConfigurableApplicationContext)testContext.getApplicationContext();
         threadApplicationContext.set(context);
 
         // mark Camel to be startable again and start Camel
@@ -87,8 +99,10 @@ public class CamelSpringBootExecutionListener extends AbstractTestExecutionListe
 
         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)
+            // dump route coverage for each test method so its accurate
+            // statistics
+            // even if spring application context is running (i.e. its not
+            // dirtied per test method)
             CamelAnnotationsHandler.handleRouteCoverageDump(context, testClass, s -> testName);
         }
     }
diff --git a/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/DisableJmxTestExecutionListener.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/CamelSpringBootTest.java
similarity index 50%
copy from components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/DisableJmxTestExecutionListener.java
copy to components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/CamelSpringBootTest.java
index 6cc9761..c915c07 100644
--- a/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/DisableJmxTestExecutionListener.java
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/CamelSpringBootTest.java
@@ -16,24 +16,22 @@
  */
 package org.apache.camel.test.spring.junit5;
 
-import org.apache.camel.api.management.JmxSystemPropertyKeys;
-import org.springframework.test.context.TestContext;
-import org.springframework.test.context.support.AbstractTestExecutionListener;
+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;
 
-/**
- * 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 {
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.test.context.TestExecutionListeners;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
 
-    @Override
-    public void afterTestClass(TestContext testContext) throws Exception {
-        if (CamelSpringTestHelper.getOriginalJmxDisabled() == null) {
-            System.clearProperty(JmxSystemPropertyKeys.DISABLED);
-        } else {
-            System.setProperty(JmxSystemPropertyKeys.DISABLED, CamelSpringTestHelper.getOriginalJmxDisabled());
-        }
-    }
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE})
+@ExtendWith(SpringExtension.class)
+@TestExecutionListeners(value = {CamelSpringTestContextLoaderTestExecutionListener.class, DisableJmxTestExecutionListener.class, CamelSpringBootExecutionListener.class,
+                                 StopWatchTestExecutionListener.class}, mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS)
+public @interface CamelSpringBootTest {
 
 }
diff --git a/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/CamelSpringTestContextLoaderTestExecutionListener.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/CamelSpringTestContextLoaderTestExecutionListener.java
index f22d5b5..2609692 100644
--- a/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/CamelSpringTestContextLoaderTestExecutionListener.java
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/CamelSpringTestContextLoaderTestExecutionListener.java
@@ -16,30 +16,29 @@
  */
 package org.apache.camel.test.spring.junit5;
 
-import org.springframework.core.Ordered;
 import org.springframework.test.context.TestContext;
 import org.springframework.test.context.support.AbstractTestExecutionListener;
 
 /**
- * Helper for {@link CamelSpringTestContextLoader} that sets the test class state
- * in {@link CamelSpringTestHelper} almost immediately before the loader initializes
- * the Spring context.
+ * 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.
+ * 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.
+     * Returns the precedence that is used by Spring to choose the appropriate
+     * execution order of test listeners.
+     * 
+     * See {@link SpringTestExecutionListenerSorter#getPrecedence(Class)} for more.
      */
     @Override
     public int getOrder() {
-        //set Camel first
-        return Ordered.HIGHEST_PRECEDENCE;
+        return SpringTestExecutionListenerSorter.getPrecedence(getClass());
     }
 
     @Override
diff --git a/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/DisableJmxTestExecutionListener.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/DisableJmxTestExecutionListener.java
index 6cc9761..11f85b7 100644
--- a/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/DisableJmxTestExecutionListener.java
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/DisableJmxTestExecutionListener.java
@@ -22,8 +22,8 @@ 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.
+ * support in Camel through the use of {@link DisableJmx}. Tries to ensure that
+ * the pre-test value is restored.
  */
 public class DisableJmxTestExecutionListener extends AbstractTestExecutionListener {
 
@@ -36,4 +36,15 @@ public class DisableJmxTestExecutionListener extends AbstractTestExecutionListen
         }
     }
 
+    /**
+     * Returns the precedence that is used by Spring to choose the appropriate
+     * execution order of test listeners.
+     * 
+     * See {@link SpringTestExecutionListenerSorter#getPrecedence(Class)} for more.
+     */
+    @Override
+    public int getOrder() {
+        return SpringTestExecutionListenerSorter.getPrecedence(getClass());
+    }
+
 }
diff --git a/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/SpringTestExecutionListenerSorter.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/SpringTestExecutionListenerSorter.java
new file mode 100644
index 0000000..08071b6
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/SpringTestExecutionListenerSorter.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.test.spring.junit5;
+
+import org.springframework.core.Ordered;
+
+/**
+ * This class centralizes the order of execution of spring test execution listeners:
+ * 1) StopWatchTestExecutionListener
+ * 2) CamelSpringBootExecutionListener
+ * 3) DisableJmxTestExecutionListener
+ * 4) CamelSpringTestContextLoaderTestExecutionListener
+ * 5) Spring default listeners
+ */
+public final class SpringTestExecutionListenerSorter {
+
+    private SpringTestExecutionListenerSorter() {
+    }
+
+    public static int getPrecedence(Class<?> clazz) {
+        if (clazz == StopWatchTestExecutionListener.class) {
+            return Ordered.HIGHEST_PRECEDENCE + 4000;
+        } else if (clazz == CamelSpringBootExecutionListener.class) {
+            return Ordered.HIGHEST_PRECEDENCE + 3000;
+        } else if (clazz == DisableJmxTestExecutionListener.class) {
+            return Ordered.HIGHEST_PRECEDENCE + 2000;
+        } else if (clazz == CamelSpringTestContextLoaderTestExecutionListener.class) {
+            return Ordered.HIGHEST_PRECEDENCE + 1000;
+        }
+        throw new IllegalArgumentException("Impossible to get the precedence of the class " + clazz.getName() + ".");
+    }
+
+}
diff --git a/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/StopWatchTestExecutionListener.java b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/StopWatchTestExecutionListener.java
index 8b6627b..d24ba1f 100644
--- a/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/StopWatchTestExecutionListener.java
+++ b/components/camel-test-spring-junit5/src/main/java/org/apache/camel/test/spring/junit5/StopWatchTestExecutionListener.java
@@ -24,14 +24,27 @@ import org.springframework.test.context.TestContext;
 import org.springframework.test.context.support.AbstractTestExecutionListener;
 
 /**
- * An execution listener that simulates the timing output built in to {@link org.apache.camel.test.junit5.CamelTestSupport}.
+ * An execution listener that simulates the timing output built in to
+ * {@link org.apache.camel.test.junit5.CamelTestSupport}.
  */
 public class StopWatchTestExecutionListener extends AbstractTestExecutionListener {
 
     protected static ThreadLocal<StopWatch> threadStopWatch = new ThreadLocal<>();
 
     /**
-     * Exists primarily for testing purposes, but allows for access to the underlying stop watch instance for a test.
+     * Returns the precedence that is used by Spring to choose the appropriate
+     * execution order of test listeners.
+     * 
+     * See {@link SpringTestExecutionListenerSorter#getPrecedence(Class)} for more.
+     */
+    @Override
+    public int getOrder() {
+        return SpringTestExecutionListenerSorter.getPrecedence(getClass());
+    }
+
+    /**
+     * 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();
diff --git a/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/SpringTestExecutionListenerSorterTest.java b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/SpringTestExecutionListenerSorterTest.java
new file mode 100644
index 0000000..e3d1ca3
--- /dev/null
+++ b/components/camel-test-spring-junit5/src/test/java/org/apache/camel/test/spring/SpringTestExecutionListenerSorterTest.java
@@ -0,0 +1,54 @@
+/*
+ * 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.ArrayList;
+import java.util.List;
+
+import org.apache.camel.test.spring.junit5.CamelSpringBootExecutionListener;
+import org.apache.camel.test.spring.junit5.CamelSpringTestContextLoaderTestExecutionListener;
+import org.apache.camel.test.spring.junit5.DisableJmxTestExecutionListener;
+import org.apache.camel.test.spring.junit5.StopWatchTestExecutionListener;
+import org.junit.jupiter.api.Test;
+
+import static org.apache.camel.test.spring.junit5.SpringTestExecutionListenerSorter.getPrecedence;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+public class SpringTestExecutionListenerSorterTest {
+
+    @Test
+    void getPrecedencesForRegisteredClassesShouldReturnCorrectOrder() {
+
+        ArrayList<Class<?>> listenersInExpectedOrder = new ArrayList<>();
+        listenersInExpectedOrder.add(StopWatchTestExecutionListener.class);
+        listenersInExpectedOrder.add(CamelSpringBootExecutionListener.class);
+        listenersInExpectedOrder.add(DisableJmxTestExecutionListener.class);
+        listenersInExpectedOrder.add(CamelSpringTestContextLoaderTestExecutionListener.class);
+
+        List<Class<?>> listenersSortedByPrecedence = new ArrayList<>(listenersInExpectedOrder);
+        listenersSortedByPrecedence.sort((c1, c2) -> Integer.compare(getPrecedence(c2), getPrecedence(c1)));
+
+        assertEquals(listenersInExpectedOrder, listenersSortedByPrecedence);
+    }
+
+    @Test
+    void getPrecedenceForWrongClassShouldThrow() {
+        assertThrows(IllegalArgumentException.class, () -> getPrecedence(Object.class));
+    }
+
+}