CamelTestSupport style of testing #3511
diff --git a/.github/workflows/ci-build.yaml b/.github/workflows/ci-build.yaml
index 299e3f8..52c5ec4 100644
--- a/.github/workflows/ci-build.yaml
+++ b/.github/workflows/ci-build.yaml
@@ -237,6 +237,12 @@
           ../mvnw ${MAVEN_ARGS} ${BRANCH_OPTIONS} \
             -Dformatter.skip -Dimpsort.skip -Denforcer.skip -Dcamel-quarkus.update-extension-doc-page.skip \
             test
+      - name: cd test-framework && mvn test
+        run: |
+          cd test-framework
+          ../mvnw ${MAVEN_ARGS} ${BRANCH_OPTIONS} \
+            -Dformatter.skip -Dimpsort.skip -Denforcer.skip -Dcamel-quarkus.update-extension-doc-page.skip \
+            test
       - name: cd docs && mvn verify
         if: github.ref != 'refs/heads/camel-main' && github.base_ref != 'camel-main'
         run: |
diff --git a/docs/modules/ROOT/pages/user-guide/testing.adoc b/docs/modules/ROOT/pages/user-guide/testing.adoc
index 24688eb..9613399 100644
--- a/docs/modules/ROOT/pages/user-guide/testing.adoc
+++ b/docs/modules/ROOT/pages/user-guide/testing.adoc
@@ -226,3 +226,45 @@
 ----
 
 More examples of WireMock usage can be found in the Camel Quarkus integration test source tree such as https://github.com/apache/camel-quarkus/tree/main/integration-tests/geocoder[Geocoder].
+
+== `CamelTestSupport` style of testing
+
+If you used plain Camel before, you may know https://camel.apache.org/components/latest/others/test-junit5.html[CamelTestSupport] already.
+Unfortunately the Camel variant won't work on Quarkus and so we prepared a replacement called `CamelQuarkusTestSupport`, which can be used in JVM mode.
+
+Please add following dependency into your module (preferably in the `test` scope), to use `CamelQuarkusTestSupport`.
+
+```
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-junit5</artifactId>
+            <scope>test</scope>
+        </dependency>
+```
+
+There are several limitations:
+
+* Methods `afterAll`, `afterEach`, `afterTestExecution`, `beforeAll` and `beforeEach` are not executed anymore.
+You should use `doAfterAll`, `doAfterConstruct`, `doAfterEach`, `doBeforeEach` instead of them.
+Be aware that execution of method `doAfterConstruct` differs from the execution of the method `beforeAll` if `@TestInstance(TestInstance.Lifecycle.PER_METHOD)` is used in which case callback is called
+ before each test.
+* The test class has to be annotated with `@io.quarkus.test.junit.QuarkusTest` and has to extend `org.apache.camel.quarkus.test.CamelQuarkusTestSupport`.
+* Camel Quarkus does not support stopping and re-starting the same `CamelContext` instance within the life cycle of a single application. You will be able to call `CamelContext.stop()`, but `CamelContext.start()` won't work.
+* Starting and stopping `CamelContext` in Camel Quarkus is generally bound to starting and stopping the application and this holds also when testing.
+* Starting and stopping the application under test (and thus also `CamelContext`) is under full control of Quarkus JUnit Extension. It prefers keeping the application up and running unless it is told to do otherwise.
+* Hence normally the application under test is started only once for all test classes of the given Maven/Gradle module.
+* To force Quarkus JUnit Extension to restart the application (and thus also `CamelContext`) for a given test class, you need to assign a unique `@io.quarkus.test.junit.TestProfile` to that class. Check the https://quarkus.io/guides/getting-started-testing#testing_different_profiles[Quarkus documentation] how you can do that. (Note that `https://quarkus.io/guides/getting-started-testing#quarkus-test-resource[@io.quarkus.test.common.QuarkusTestResource]` has a similar effect.)
+*  Camel Quarkus executes the production of beans during the build phase. Because all the tests are
+build together,  exclusion behavior is implemented into `CamelQuarkusTestSupport`. If a producer of the specific type and name is used in one tests, the instance will be the same for the rest of the tests.
+* JUnit Jupiter callbacks (`BeforeEachCallback`, `AfterEachCallback`, `AfterAllCallback`, `BeforeAllCallback`, `BeforeTestExecutionCallback` and `AfterTestExecutionCallback`) might not work correctly. See the https://quarkus.io/guides/getting-started-testing#enrichment-via-quarkustestcallback[documentation].
+
+
+[source,java]
+----
+@QuarkusTest
+@TestProfile(SimpleTest.class) //necessary only if "newly created" context is required for the test (worse performance)
+public class SimpleTest extends CamelQuarkusTestSupport {
+    ...
+}
+----
+
diff --git a/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/InjectionPointsProcessor.java b/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/InjectionPointsProcessor.java
index e8ced17..2e15c9c 100644
--- a/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/InjectionPointsProcessor.java
+++ b/extensions-core/core/deployment/src/main/java/org/apache/camel/quarkus/core/deployment/InjectionPointsProcessor.java
@@ -78,6 +78,8 @@
             .createSimple(EndpointInject.class.getName());
     private static final DotName PRODUCE_ANNOTATION = DotName
             .createSimple(Produce.class.getName());
+    private static final DotName TEST_SUPPORT_CLASS_NAME = DotName
+            .createSimple("org.apache.camel.quarkus.test.CamelQuarkusTestSupport");
 
     private static SyntheticBeanBuildItem syntheticBean(DotName name, Supplier<?> creator) {
         return SyntheticBeanBuildItem.configure(name)
@@ -226,12 +228,16 @@
             BuildProducer<SyntheticBeanBuildItem> syntheticBeans,
             BuildProducer<NativeImageProxyDefinitionBuildItem> proxyDefinitions) {
 
+        Set<String> alreadyCreated = new HashSet<>();
+
         for (AnnotationInstance annot : index.getIndex().getAnnotations(ENDPOINT_INJECT_ANNOTATION)) {
             final AnnotationTarget target = annot.target();
             switch (target.kind()) {
             case FIELD: {
                 final FieldInfo field = target.asField();
-                endpointInjectBeans(recorder, syntheticBeans, index.getIndex(), annot, field.type().name());
+                if (!excludeTestSyntheticBeanDuplicities(annot, alreadyCreated, field.declaringClass(), index.getIndex())) {
+                    endpointInjectBeans(recorder, syntheticBeans, index.getIndex(), annot, field.type().name());
+                }
                 break;
             }
             case METHOD: {
@@ -251,8 +257,10 @@
             switch (target.kind()) {
             case FIELD: {
                 final FieldInfo field = target.asField();
-                produceBeans(recorder, capabilities, syntheticBeans, proxyDefinitions, beanCapabilityAvailable,
-                        index.getIndex(), annot, field.type().name(), field.name(), field.declaringClass().name());
+                if (!excludeTestSyntheticBeanDuplicities(annot, alreadyCreated, field.declaringClass(), index.getIndex())) {
+                    produceBeans(recorder, capabilities, syntheticBeans, proxyDefinitions, beanCapabilityAvailable,
+                            index.getIndex(), annot, field.type().name(), field.name(), field.declaringClass().name());
+                }
                 break;
             }
             case METHOD: {
@@ -266,6 +274,45 @@
         }
     }
 
+    private boolean excludeTestSyntheticBeanDuplicities(AnnotationInstance annot, Set<String> alreadyCreated,
+            ClassInfo declaringClass, IndexView index) {
+        String identifier = annot.toString(false) + ":" + getTargetClass(annot).toString();
+
+        if (extendsCamelQuarkusTest(declaringClass, index)) {
+            if (alreadyCreated.contains(identifier)) {
+                return true;
+            } else {
+                alreadyCreated.add(identifier);
+            }
+        }
+        return false;
+    }
+
+    private DotName getTargetClass(AnnotationInstance annot) {
+        switch (annot.target().kind()) {
+        case FIELD:
+            return annot.target().asField().type().name();
+        case METHOD:
+            return annot.target().asMethod().returnType().name();
+        default:
+            return null;
+        }
+    }
+
+    private boolean extendsCamelQuarkusTest(ClassInfo declaringClass, IndexView indexView) {
+        if (declaringClass == null) {
+            return false;
+        }
+
+        if (TEST_SUPPORT_CLASS_NAME.equals(declaringClass.name())) {
+            return true;
+        }
+
+        //iterate over parent until found CamelQuarkusTest or null
+        return (declaringClass.superName() != null &&
+                extendsCamelQuarkusTest(indexView.getClassByName(declaringClass.superName()), indexView));
+    }
+
     void produceBeans(CamelRecorder recorder, List<CapabilityBuildItem> capabilities,
             BuildProducer<SyntheticBeanBuildItem> syntheticBeans,
             BuildProducer<NativeImageProxyDefinitionBuildItem> proxyDefinitions,
diff --git a/extensions-core/core/runtime/src/main/java/org/apache/camel/quarkus/core/FastCamelContext.java b/extensions-core/core/runtime/src/main/java/org/apache/camel/quarkus/core/FastCamelContext.java
index 95c5254..91302bf 100644
--- a/extensions-core/core/runtime/src/main/java/org/apache/camel/quarkus/core/FastCamelContext.java
+++ b/extensions-core/core/runtime/src/main/java/org/apache/camel/quarkus/core/FastCamelContext.java
@@ -81,7 +81,9 @@
     @Override
     protected Registry createRegistry() {
         // Registry creation is done at build time
-        throw new UnsupportedOperationException();
+        throw new UnsupportedOperationException(
+                "In case that the test based on CamelQuarkusTestSupport throws this exception, " +
+                        "be aware that re-starting of context is not possible.");
     }
 
     @Override
diff --git a/pom.xml b/pom.xml
index 140ac00..9b1b130 100644
--- a/pom.xml
+++ b/pom.xml
@@ -226,6 +226,7 @@
         <module>integration-test-groups</module>
         <module>docs</module>
         <module>integration-tests-jvm</module>
+        <module>test-framework</module>
     </modules>
 
     <developers>
@@ -594,6 +595,10 @@
                             <path>integration-tests-support</path>
                             <artifactIdPrefix>camel-quarkus-integration-test-support-</artifactIdPrefix>
                         </extensionDir>
+                        <extensionDir>
+                            <path>test-framework</path>
+                            <artifactIdPrefix>camel-quarkus-test-framework</artifactIdPrefix>
+                        </extensionDir>
                     </extensionDirs>
                 </configuration>
             </plugin>
diff --git a/poms/bom/pom.xml b/poms/bom/pom.xml
index 65f7f74..52b38df 100644
--- a/poms/bom/pom.xml
+++ b/poms/bom/pom.xml
@@ -7772,6 +7772,11 @@
             </dependency>
             <dependency>
                 <groupId>org.apache.camel.quarkus</groupId>
+                <artifactId>camel-quarkus-junit5</artifactId>
+                <version>${camel-quarkus.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.camel.quarkus</groupId>
                 <artifactId>camel-quarkus-kafka</artifactId>
                 <version>${camel-quarkus.version}</version>
             </dependency>
diff --git a/poms/bom/src/main/generated/flattened-full-pom.xml b/poms/bom/src/main/generated/flattened-full-pom.xml
index 693bf95..2053129 100644
--- a/poms/bom/src/main/generated/flattened-full-pom.xml
+++ b/poms/bom/src/main/generated/flattened-full-pom.xml
@@ -7716,6 +7716,11 @@
       </dependency>
       <dependency>
         <groupId>org.apache.camel.quarkus</groupId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+        <artifactId>camel-quarkus-junit5</artifactId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+        <version>2.12.0-SNAPSHOT</version><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+      </dependency>
+      <dependency>
+        <groupId>org.apache.camel.quarkus</groupId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
         <artifactId>camel-quarkus-kafka</artifactId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
         <version>2.12.0-SNAPSHOT</version><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
       </dependency>
diff --git a/poms/bom/src/main/generated/flattened-reduced-pom.xml b/poms/bom/src/main/generated/flattened-reduced-pom.xml
index f781f2a..061ec71 100644
--- a/poms/bom/src/main/generated/flattened-reduced-pom.xml
+++ b/poms/bom/src/main/generated/flattened-reduced-pom.xml
@@ -7716,6 +7716,11 @@
       </dependency>
       <dependency>
         <groupId>org.apache.camel.quarkus</groupId>
+        <artifactId>camel-quarkus-junit5</artifactId>
+        <version>2.12.0-SNAPSHOT</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.camel.quarkus</groupId>
         <artifactId>camel-quarkus-kafka</artifactId>
         <version>2.12.0-SNAPSHOT</version>
       </dependency>
diff --git a/poms/bom/src/main/generated/flattened-reduced-verbose-pom.xml b/poms/bom/src/main/generated/flattened-reduced-verbose-pom.xml
index 4877a13..97cdccb 100644
--- a/poms/bom/src/main/generated/flattened-reduced-verbose-pom.xml
+++ b/poms/bom/src/main/generated/flattened-reduced-verbose-pom.xml
@@ -7716,6 +7716,11 @@
       </dependency>
       <dependency>
         <groupId>org.apache.camel.quarkus</groupId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+        <artifactId>camel-quarkus-junit5</artifactId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+        <version>2.12.0-SNAPSHOT</version><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
+      </dependency>
+      <dependency>
+        <groupId>org.apache.camel.quarkus</groupId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
         <artifactId>camel-quarkus-kafka</artifactId><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
         <version>2.12.0-SNAPSHOT</version><!-- org.apache.camel.quarkus:camel-quarkus-bom:${project.version} -->
       </dependency>
diff --git a/test-framework/junit5-extension-tests/pom.xml b/test-framework/junit5-extension-tests/pom.xml
new file mode 100644
index 0000000..5d807f5
--- /dev/null
+++ b/test-framework/junit5-extension-tests/pom.xml
@@ -0,0 +1,69 @@
+<?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="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <groupId>org.apache.camel.quarkus</groupId>
+        <artifactId>camel-quarkus-test-framework</artifactId>
+        <version>2.12.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>camel-quarkus-junit5-extension-tests</artifactId>
+    <name>Camel Quarkus :: Test Framework :: Junit5 :: Extension Tests</name>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.assertj</groupId>
+            <artifactId>assertj-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-junit5-internal</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.rest-assured</groupId>
+            <artifactId>rest-assured</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-resteasy</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-junit5</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-file</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-direct</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/test-framework/junit5-extension-tests/src/test/java/org/apache/camel/quarkus/test/extensions/continousDev/ContinuousDevTest.java b/test-framework/junit5-extension-tests/src/test/java/org/apache/camel/quarkus/test/extensions/continousDev/ContinuousDevTest.java
new file mode 100644
index 0000000..fbab891
--- /dev/null
+++ b/test-framework/junit5-extension-tests/src/test/java/org/apache/camel/quarkus/test/extensions/continousDev/ContinuousDevTest.java
@@ -0,0 +1,77 @@
+/*
+ * 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.quarkus.test.extensions.continousDev;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+import io.quarkus.test.ContinuousTestingTestUtils;
+import io.quarkus.test.QuarkusDevModeTest;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.StringAsset;
+import org.jboss.shrinkwrap.api.spec.JavaArchive;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+public class ContinuousDevTest {
+
+    private static final Path LOG_FILE = Paths.get("target/" + ContinuousDevTest.class.getSimpleName() + ".log");
+
+    @RegisterExtension
+    static final QuarkusDevModeTest TEST = new QuarkusDevModeTest()
+            .setArchiveProducer(new Supplier<>() {
+                @Override
+                public JavaArchive get() {
+                    return ShrinkWrap.create(JavaArchive.class).addClasses(HelloResource.class)
+                            .add(new StringAsset(
+                                    ContinuousTestingTestUtils.appProperties("camel-quarkus.junit5.message=Sheldon")),
+                                    "application.properties");
+                }
+            })
+            .setTestArchiveProducer(new Supplier<>() {
+                @Override
+                public JavaArchive get() {
+                    return ShrinkWrap.create(JavaArchive.class).addClasses(HelloET.class);
+                }
+            });
+
+    @Test
+    public void checkTests() throws InterruptedException {
+        ContinuousTestingTestUtils utils = new ContinuousTestingTestUtils();
+        ContinuousTestingTestUtils.TestStatus ts = utils.waitForNextCompletion();
+
+        Assertions.assertEquals(2L, ts.getTestsFailed());
+        Assertions.assertEquals(1L, ts.getTestsPassed());
+        Assertions.assertEquals(0L, ts.getTestsSkipped());
+
+        TEST.modifyResourceFile("application.properties", new Function<String, String>() {
+            @Override
+            public String apply(String s) {
+                return ContinuousTestingTestUtils.appProperties("camel-quarkus.junit5.message=Leonard");
+            }
+        });
+        ts = utils.waitForNextCompletion();
+
+        Assertions.assertEquals(1L, ts.getTestsFailed());
+        Assertions.assertEquals(2L, ts.getTestsPassed());
+        Assertions.assertEquals(0L, ts.getTestsSkipped());
+
+    }
+}
diff --git a/test-framework/junit5-extension-tests/src/test/java/org/apache/camel/quarkus/test/extensions/continousDev/HelloET.java b/test-framework/junit5-extension-tests/src/test/java/org/apache/camel/quarkus/test/extensions/continousDev/HelloET.java
new file mode 100644
index 0000000..94e26e1
--- /dev/null
+++ b/test-framework/junit5-extension-tests/src/test/java/org/apache/camel/quarkus/test/extensions/continousDev/HelloET.java
@@ -0,0 +1,79 @@
+/*
+ * 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.quarkus.test.extensions.continousDev;
+
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import io.quarkus.test.junit.QuarkusTest;
+import io.restassured.RestAssured;
+import org.apache.camel.quarkus.test.CamelQuarkusTestSupport;
+import org.junit.jupiter.api.Test;
+
+import static org.hamcrest.CoreMatchers.is;
+
+@QuarkusTest
+public class HelloET extends CamelQuarkusTestSupport {
+
+    @Test
+    public void hello1Test() throws Exception {
+        Files.createDirectories(testDirectory());
+        Path testFile = testFile("hello.txt");
+        Files.write(testFile, "Hello ".getBytes(StandardCharsets.UTF_8));
+
+        RestAssured.given()
+                .body(fileUri() + "?fileName=hello.txt")
+                .post("/hello/message")
+
+                .then()
+                .statusCode(200)
+                .body(is("Hello Sheldon"));
+
+    }
+
+    @Test
+    public void hello2Test() throws Exception {
+        Files.createDirectories(testDirectory());
+        Path testFile = testFile("hello.txt");
+        Files.write(testFile, "Hello ".getBytes(StandardCharsets.UTF_8));
+
+        RestAssured.given()
+                .body(fileUri() + "?fileName=hello.txt")
+                .post("/hello/message")
+
+                .then()
+                .statusCode(200)
+                .body(is("Hello Leonard"));
+    }
+
+    @Test
+    public void hello3Test() throws Exception {
+        Files.createDirectories(testDirectory());
+        Path testFile = testFile("hello.txt");
+        Files.write(testFile, "Hello ".getBytes(StandardCharsets.UTF_8));
+
+        RestAssured.given()
+                .body(fileUri() + "?fileName=hello.txt")
+                .post("/hello/message")
+
+                .then()
+                .statusCode(200)
+                .body(is("Hello Leonard"));
+    }
+
+}
diff --git a/test-framework/junit5-extension-tests/src/test/java/org/apache/camel/quarkus/test/extensions/continousDev/HelloResource.java b/test-framework/junit5-extension-tests/src/test/java/org/apache/camel/quarkus/test/extensions/continousDev/HelloResource.java
new file mode 100644
index 0000000..8dfcc6e
--- /dev/null
+++ b/test-framework/junit5-extension-tests/src/test/java/org/apache/camel/quarkus/test/extensions/continousDev/HelloResource.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.quarkus.test.extensions.continousDev;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import org.apache.camel.ConsumerTemplate;
+import org.apache.camel.ProducerTemplate;
+import org.eclipse.microprofile.config.inject.ConfigProperty;
+
+@Path("/hello")
+@ApplicationScoped
+public class HelloResource {
+
+    @ConfigProperty(name = "camel-quarkus.junit5.message")
+    String message;
+
+    @Inject
+    ProducerTemplate producerTemplate;
+
+    @Inject
+    ConsumerTemplate consumerTemplate;
+
+    @Path("/message")
+    @POST
+    @Produces(MediaType.TEXT_PLAIN)
+    public String getMessage(String body) {
+        return consumerTemplate.receiveBodyNoWait(body, String.class) + message;
+    }
+}
diff --git a/test-framework/junit5-extension-tests/src/test/java/org/apache/camel/quarkus/test/extensions/routeBuilder/HelloRouteBuilder.java b/test-framework/junit5-extension-tests/src/test/java/org/apache/camel/quarkus/test/extensions/routeBuilder/HelloRouteBuilder.java
new file mode 100644
index 0000000..b611cb2
--- /dev/null
+++ b/test-framework/junit5-extension-tests/src/test/java/org/apache/camel/quarkus/test/extensions/routeBuilder/HelloRouteBuilder.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.quarkus.test.extensions.routeBuilder;
+
+import javax.enterprise.context.ApplicationScoped;
+
+import org.apache.camel.builder.RouteBuilder;
+
+@ApplicationScoped
+public class HelloRouteBuilder extends RouteBuilder {
+
+    @Override
+    public void configure() {
+        from("direct:in").routeId("directRoute").to("file:target/data/RouteBuilderET?filename=hello_false.txt");
+    }
+
+}
diff --git a/test-framework/junit5-extension-tests/src/test/java/org/apache/camel/quarkus/test/extensions/routeBuilder/RouteBuilderFalseET.java b/test-framework/junit5-extension-tests/src/test/java/org/apache/camel/quarkus/test/extensions/routeBuilder/RouteBuilderFalseET.java
new file mode 100644
index 0000000..4723080
--- /dev/null
+++ b/test-framework/junit5-extension-tests/src/test/java/org/apache/camel/quarkus/test/extensions/routeBuilder/RouteBuilderFalseET.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.quarkus.test.extensions.routeBuilder;
+
+import io.quarkus.test.junit.QuarkusTest;
+import io.restassured.RestAssured;
+import org.apache.camel.quarkus.test.CamelQuarkusTestSupport;
+import org.junit.jupiter.api.Test;
+
+import static org.hamcrest.CoreMatchers.is;
+
+@QuarkusTest
+public class RouteBuilderFalseET extends CamelQuarkusTestSupport {
+
+    @Override
+    public boolean isUseRouteBuilder() {
+        return false;
+    }
+
+    @Test
+    public void helloTest() throws Exception {
+        RestAssured.given()
+                .body("Hello (from routeBuilder) ")
+                .post("/routeBuilder/in")
+                .then()
+                .statusCode(204);
+
+        RestAssured.given()
+                .body("file:target/data/RouteBuilderET?fileName=hello_false.txt")
+                .post("/hello/message")
+                .then()
+                .statusCode(200)
+                .body(is("Hello (from routeBuilder) Sheldon"));
+    }
+
+    @Test
+    public void hello2Test() throws Exception {
+        helloTest();
+    }
+
+}
diff --git a/test-framework/junit5-extension-tests/src/test/java/org/apache/camel/quarkus/test/extensions/routeBuilder/RouteBuilderResource.java b/test-framework/junit5-extension-tests/src/test/java/org/apache/camel/quarkus/test/extensions/routeBuilder/RouteBuilderResource.java
new file mode 100644
index 0000000..5cab10c
--- /dev/null
+++ b/test-framework/junit5-extension-tests/src/test/java/org/apache/camel/quarkus/test/extensions/routeBuilder/RouteBuilderResource.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.quarkus.test.extensions.routeBuilder;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import org.apache.camel.ProducerTemplate;
+
+@Path("/routeBuilder")
+@ApplicationScoped
+public class RouteBuilderResource {
+
+    @Inject
+    ProducerTemplate producerTemplate;
+
+    @Path("/in")
+    @POST
+    @Produces(MediaType.TEXT_PLAIN)
+    public void in(String body) {
+        producerTemplate.sendBody("direct:in", body);
+    }
+
+}
diff --git a/test-framework/junit5-extension-tests/src/test/java/org/apache/camel/quarkus/test/extensions/routeBuilder/RouteBuilderTest.java b/test-framework/junit5-extension-tests/src/test/java/org/apache/camel/quarkus/test/extensions/routeBuilder/RouteBuilderTest.java
new file mode 100644
index 0000000..5a78302
--- /dev/null
+++ b/test-framework/junit5-extension-tests/src/test/java/org/apache/camel/quarkus/test/extensions/routeBuilder/RouteBuilderTest.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.quarkus.test.extensions.routeBuilder;
+
+import java.util.function.Supplier;
+
+import io.quarkus.test.ContinuousTestingTestUtils;
+import io.quarkus.test.QuarkusDevModeTest;
+import org.apache.camel.quarkus.test.extensions.continousDev.HelloResource;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.StringAsset;
+import org.jboss.shrinkwrap.api.spec.JavaArchive;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+public class RouteBuilderTest {
+
+    @RegisterExtension
+    static final QuarkusDevModeTest TEST = new QuarkusDevModeTest()
+            .setArchiveProducer(new Supplier<>() {
+                @Override
+                public JavaArchive get() {
+                    return ShrinkWrap.create(JavaArchive.class)
+                            .addClasses(RouteBuilderResource.class, HelloRouteBuilder.class, HelloResource.class)
+                            .add(new StringAsset(
+                                    ContinuousTestingTestUtils.appProperties("camel-quarkus.junit5.message=Sheldon")),
+                                    "application.properties");
+                }
+            })
+            .setTestArchiveProducer(new Supplier<>() {
+                @Override
+                public JavaArchive get() {
+                    return ShrinkWrap.create(JavaArchive.class).addClasses(RouteBuilderFalseET.class, RouteBuilderTrueET.class);
+                }
+            });
+
+    @Test
+    public void checkTests() throws InterruptedException {
+        ContinuousTestingTestUtils utils = new ContinuousTestingTestUtils();
+        ContinuousTestingTestUtils.TestStatus ts = utils.waitForNextCompletion();
+
+        Assertions.assertEquals(0L, ts.getTestsFailed());
+        Assertions.assertEquals(4L, ts.getTestsPassed());
+        Assertions.assertEquals(0L, ts.getTestsSkipped());
+    }
+}
diff --git a/test-framework/junit5-extension-tests/src/test/java/org/apache/camel/quarkus/test/extensions/routeBuilder/RouteBuilderTrueET.java b/test-framework/junit5-extension-tests/src/test/java/org/apache/camel/quarkus/test/extensions/routeBuilder/RouteBuilderTrueET.java
new file mode 100644
index 0000000..263dcc3
--- /dev/null
+++ b/test-framework/junit5-extension-tests/src/test/java/org/apache/camel/quarkus/test/extensions/routeBuilder/RouteBuilderTrueET.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.test.extensions.routeBuilder;
+
+import io.quarkus.test.junit.QuarkusTest;
+import io.restassured.RestAssured;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.quarkus.test.CamelQuarkusTestSupport;
+import org.junit.jupiter.api.Test;
+
+import static org.hamcrest.CoreMatchers.is;
+
+@QuarkusTest
+public class RouteBuilderTrueET extends CamelQuarkusTestSupport {
+
+    @Override
+    public boolean isUseRouteBuilder() {
+        return true;
+    }
+
+    @Test
+    public void helloTest() throws Exception {
+        RestAssured.given()
+                .body("Hello (from routeBuilder) ")
+                .post("/routeBuilder/in")
+                .then()
+                .statusCode(204);
+
+        RestAssured.given()
+                .body("file:target/data/RouteBuilderET?fileName=hello_true.txt")
+                .post("/hello/message")
+                .then()
+                .statusCode(200)
+                .body(is("Hello (from routeBuilder) Sheldon"));
+    }
+
+    @Test
+    public void hello2Test() throws Exception {
+        helloTest();
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                from("direct:in").routeId("directRoute").to("file:target/data/RouteBuilderET?filename=hello_true.txt");
+            }
+        };
+    }
+}
diff --git a/test-framework/junit5/pom.xml b/test-framework/junit5/pom.xml
new file mode 100644
index 0000000..2deb8a4
--- /dev/null
+++ b/test-framework/junit5/pom.xml
@@ -0,0 +1,78 @@
+<?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="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <groupId>org.apache.camel.quarkus</groupId>
+        <artifactId>camel-quarkus-test-framework</artifactId>
+        <version>2.12.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>camel-quarkus-junit5</artifactId>
+    <name>Camel Quarkus :: Test Framework :: Junit5</name>
+
+    <dependencies>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-junit5</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-test-junit5</artifactId>
+            <exclusions>
+                <exclusion>
+                    <artifactId>camel-directvm</artifactId>
+                    <groupId>org.apache.camel</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-bean</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            <artifactId>camel-quarkus-management</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.awaitility</groupId>
+            <artifactId>awaitility</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <configuration>
+                    <runOrder>alphabetical</runOrder>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/test-framework/junit5/src/main/java/org/apache/camel/quarkus/test/AfterAllCallback.java b/test-framework/junit5/src/main/java/org/apache/camel/quarkus/test/AfterAllCallback.java
new file mode 100644
index 0000000..011e008
--- /dev/null
+++ b/test-framework/junit5/src/main/java/org/apache/camel/quarkus/test/AfterAllCallback.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.quarkus.test;
+
+import io.quarkus.test.junit.callback.QuarkusTestAfterAllCallback;
+import io.quarkus.test.junit.callback.QuarkusTestContext;
+
+public class AfterAllCallback implements QuarkusTestAfterAllCallback {
+
+    @Override
+    public void afterAll(QuarkusTestContext context) {
+        if (context.getTestInstance() instanceof CamelQuarkusTestSupport) {
+            CamelQuarkusTestSupport testInstance = (CamelQuarkusTestSupport) context.getTestInstance();
+
+            if (CallbackUtil.isPerClass(testInstance)) {
+                CallbackUtil.resetContext(testInstance);
+                testInstance.internalAfterAll(context);
+            }
+
+            try {
+                testInstance.doAfterAll(context);
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+}
diff --git a/test-framework/junit5/src/main/java/org/apache/camel/quarkus/test/AfterConstructCallback.java b/test-framework/junit5/src/main/java/org/apache/camel/quarkus/test/AfterConstructCallback.java
new file mode 100644
index 0000000..fb1a07c
--- /dev/null
+++ b/test-framework/junit5/src/main/java/org/apache/camel/quarkus/test/AfterConstructCallback.java
@@ -0,0 +1,35 @@
+/*
+ * 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.quarkus.test;
+
+import io.quarkus.test.junit.callback.QuarkusTestAfterConstructCallback;
+
+public class AfterConstructCallback implements QuarkusTestAfterConstructCallback {
+
+    @Override
+    public void afterConstruct(Object testInstance) {
+        if (testInstance instanceof CamelQuarkusTestSupport) {
+            CamelQuarkusTestSupport testSupport = (CamelQuarkusTestSupport) testInstance;
+
+            try {
+                testSupport.doAfterConstruct();
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+}
diff --git a/test-framework/junit5/src/main/java/org/apache/camel/quarkus/test/AfterEachCallback.java b/test-framework/junit5/src/main/java/org/apache/camel/quarkus/test/AfterEachCallback.java
new file mode 100644
index 0000000..dcf78de
--- /dev/null
+++ b/test-framework/junit5/src/main/java/org/apache/camel/quarkus/test/AfterEachCallback.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.quarkus.test;
+
+import io.quarkus.test.junit.callback.QuarkusTestAfterEachCallback;
+import io.quarkus.test.junit.callback.QuarkusTestMethodContext;
+
+public class AfterEachCallback implements QuarkusTestAfterEachCallback {
+
+    @Override
+    public void afterEach(QuarkusTestMethodContext context) {
+        if (context.getTestInstance() instanceof CamelQuarkusTestSupport) {
+            CamelQuarkusTestSupport testInstance = (CamelQuarkusTestSupport) context.getTestInstance();
+
+            if (!CallbackUtil.isPerClass(testInstance)) {
+                CallbackUtil.resetContext(testInstance);
+            }
+
+            try {
+                testInstance.doAfterEach(context);
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+
+            }
+        }
+    }
+}
diff --git a/test-framework/junit5/src/main/java/org/apache/camel/quarkus/test/BeforeEachCallback.java b/test-framework/junit5/src/main/java/org/apache/camel/quarkus/test/BeforeEachCallback.java
new file mode 100644
index 0000000..f790372
--- /dev/null
+++ b/test-framework/junit5/src/main/java/org/apache/camel/quarkus/test/BeforeEachCallback.java
@@ -0,0 +1,53 @@
+/*
+ * 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.quarkus.test;
+
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.stream.Collectors;
+
+import io.quarkus.test.junit.callback.QuarkusTestBeforeEachCallback;
+import io.quarkus.test.junit.callback.QuarkusTestMethodContext;
+import org.junit.jupiter.api.extension.ExtensionContext;
+
+public class BeforeEachCallback implements QuarkusTestBeforeEachCallback {
+
+    @Override
+    public void beforeEach(QuarkusTestMethodContext context) {
+        if (context.getTestInstance() instanceof CamelQuarkusTestSupport) {
+            CamelQuarkusTestSupport testInstance = (CamelQuarkusTestSupport) context.getTestInstance();
+            ExtensionContext mockContext = new CallbackUtil.MockExtensionContext(CallbackUtil.getLifecycle(testInstance),
+                    getDisplayName(context.getTestMethod()));
+
+            try {
+                testInstance.internalBeforeEach(mockContext);
+                testInstance.internalBeforeAll(mockContext);
+                testInstance.doBeforeEach(context);
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+
+        }
+    }
+
+    private String getDisplayName(Method method) {
+        return String.format("%s(%s)",
+                method.getName(),
+                Arrays.stream(method.getParameterTypes()).map(c -> c.getSimpleName()).collect(Collectors.joining(", ")));
+    }
+
+}
diff --git a/test-framework/junit5/src/main/java/org/apache/camel/quarkus/test/CallbackUtil.java b/test-framework/junit5/src/main/java/org/apache/camel/quarkus/test/CallbackUtil.java
new file mode 100644
index 0000000..eee10d5
--- /dev/null
+++ b/test-framework/junit5/src/main/java/org/apache/camel/quarkus/test/CallbackUtil.java
@@ -0,0 +1,166 @@
+/*
+ * 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.quarkus.test;
+
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Method;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Function;
+
+import org.apache.camel.component.mock.MockEndpoint;
+import org.junit.jupiter.api.TestInstance;
+import org.junit.jupiter.api.extension.ExtensionContext;
+import org.junit.jupiter.api.extension.TestInstances;
+import org.junit.jupiter.api.parallel.ExecutionMode;
+import org.junit.jupiter.engine.execution.ExtensionValuesStore;
+import org.junit.jupiter.engine.execution.NamespaceAwareStore;
+
+public class CallbackUtil {
+
+    static boolean isPerClass(CamelQuarkusTestSupport testSupport) {
+        return getLifecycle(testSupport).filter(lc -> lc.equals(TestInstance.Lifecycle.PER_CLASS)).isPresent();
+    }
+
+    static Optional<TestInstance.Lifecycle> getLifecycle(CamelQuarkusTestSupport testSupport) {
+        if (testSupport.getClass().getAnnotation(TestInstance.class) != null) {
+            return Optional.of(testSupport.getClass().getAnnotation(TestInstance.class).value());
+        }
+
+        return Optional.empty();
+    }
+
+    static void resetContext(CamelQuarkusTestSupport testInstance) {
+
+        //if routeBuilder (from the test) was used, all routes has to be stopped and removed
+        //because routes will be created again (in case of TestInstance.Lifecycle.PER_CLASS, this method is not executed)
+        if (testInstance.isUseRouteBuilder()) {
+            try {
+                testInstance.context().getRouteController().stopAllRoutes();
+                testInstance.context().getRouteController().removeAllRoutes();
+
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        testInstance.context().getComponentNames().forEach(cn -> testInstance.context().removeComponent(cn));
+        MockEndpoint.resetMocks(testInstance.context());
+    }
+
+    static class MockExtensionContext implements ExtensionContext {
+
+        private final Optional<TestInstance.Lifecycle> lifecycle;
+        private final String currentTestName;
+        private final ExtensionContext.Store globalStore;
+
+        public MockExtensionContext(Optional<TestInstance.Lifecycle> lifecycle, String currentTestName) {
+            this.lifecycle = lifecycle;
+            this.currentTestName = currentTestName;
+            this.globalStore = new NamespaceAwareStore(new ExtensionValuesStore(null), ExtensionContext.Namespace.GLOBAL);
+        }
+
+        @Override
+        public Optional<ExtensionContext> getParent() {
+            return Optional.empty();
+        }
+
+        @Override
+        public ExtensionContext getRoot() {
+            return null;
+        }
+
+        @Override
+        public String getUniqueId() {
+            return null;
+        }
+
+        @Override
+        public String getDisplayName() {
+            return currentTestName;
+        }
+
+        @Override
+        public Set<String> getTags() {
+            return null;
+        }
+
+        @Override
+        public Optional<AnnotatedElement> getElement() {
+            return Optional.empty();
+        }
+
+        @Override
+        public Optional<Class<?>> getTestClass() {
+            return Optional.empty();
+        }
+
+        @Override
+        public Optional<TestInstance.Lifecycle> getTestInstanceLifecycle() {
+            return lifecycle;
+        }
+
+        @Override
+        public Optional<Object> getTestInstance() {
+            return Optional.empty();
+        }
+
+        @Override
+        public Optional<TestInstances> getTestInstances() {
+            return Optional.empty();
+        }
+
+        @Override
+        public Optional<Method> getTestMethod() {
+            return Optional.empty();
+        }
+
+        @Override
+        public Optional<Throwable> getExecutionException() {
+            return Optional.empty();
+        }
+
+        @Override
+        public Optional<String> getConfigurationParameter(String key) {
+            return Optional.empty();
+        }
+
+        @Override
+        public <T> Optional<T> getConfigurationParameter(String key, Function<String, T> transformer) {
+            return Optional.empty();
+        }
+
+        @Override
+        public void publishReportEntry(Map<String, String> map) {
+
+        }
+
+        @Override
+        public Store getStore(Namespace namespace) {
+            if (namespace == Namespace.GLOBAL) {
+                return globalStore;
+            }
+            return null;
+        }
+
+        @Override
+        public ExecutionMode getExecutionMode() {
+            return null;
+        }
+    }
+}
diff --git a/test-framework/junit5/src/main/java/org/apache/camel/quarkus/test/CamelQuarkusTestSupport.java b/test-framework/junit5/src/main/java/org/apache/camel/quarkus/test/CamelQuarkusTestSupport.java
new file mode 100644
index 0000000..9808b00
--- /dev/null
+++ b/test-framework/junit5/src/main/java/org/apache/camel/quarkus/test/CamelQuarkusTestSupport.java
@@ -0,0 +1,306 @@
+/*
+ * 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.quarkus.test;
+
+import java.util.List;
+
+import javax.inject.Inject;
+
+import io.quarkus.test.junit.QuarkusTestProfile;
+import io.quarkus.test.junit.callback.QuarkusTestContext;
+import io.quarkus.test.junit.callback.QuarkusTestMethodContext;
+import org.apache.camel.CamelContext;
+import org.apache.camel.Service;
+import org.apache.camel.model.ModelCamelContext;
+import org.apache.camel.model.RouteDefinition;
+import org.apache.camel.quarkus.core.FastCamelContext;
+import org.apache.camel.spi.Registry;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.extension.ExtensionContext;
+
+/**
+ * The {@link CamelTestSupport} class does not work on Quarkus. This class provides a replacement, which can be used in
+ * JVM mode.
+ * <p>
+ * There are several differences between {@link CamelTestSupport} and this class:
+ * <ul>
+ * <li>Starting and stopping `CamelContext` in Camel Quarkus is generally bound to starting and stopping the application
+ * and this holds also when testing.</li>
+ * <li>Starting and stopping the application under test (and thus also `CamelContext`) is under full control of Quarkus
+ * JUnit Extension. It prefers keeping the application up and running unless it is told to do otherwise.</li>
+ * <li>Hence normally the application under test is started only once for all test classes of the given Maven/Gradle
+ * module.</li>
+ * <li>To force Quarkus JUnit Extension to restart the application (and thus also `CamelContext`) for a given test
+ * class, you need to assign a unique `@io.quarkus.test.junit.TestProfile` to that class. Check the
+ * https://quarkus.io/guides/getting-started-testing#testing_different_profiles[Quarkus documentation] how you can do
+ * that. (Note that
+ * `https://quarkus.io/guides/getting-started-testing#quarkus-test-resource[@io.quarkus.test.common.QuarkusTestResource]`
+ * has a similar effect.)</li>
+ * <li>Camel Quarkus executes the production of beans during the build phase. Because all the tests are
+ * build together, exclusion behavior is implemented into `CamelQuarkusTestSupport`. If a producer of the specific type
+ * and name is used in one tests, the instance will be the same for the rest of the tests.</li>
+ * <li>Unit Jupiter callbacks (`BeforeEachCallback`, `AfterEachCallback`, `AfterAllCallback`, `BeforeAllCallback`,
+ * `BeforeTestExecutionCallback` and `AfterTestExecutionCallback`) might not work correctly. See the
+ * <a href="https://quarkus.io/guides/getting-started-testing#enrichment-via-quarkustestcallback">documentation</a>.
+ * Methods `afterAll`, `afterEach`, `afterTestExecution`, `beforeAll` and `beforeEach` are not executed anymore.
+ * You should use `doAfterAll`, `doAfterConstruct`, `doAfterEach`, `doBeforeEach` and `doBeforeAll` instead of
+ * them.</li>
+ * </ul>
+ * </p>
+ */
+public class CamelQuarkusTestSupport extends CamelTestSupport
+        implements QuarkusTestProfile {
+
+    //Flag, whether routes was created by test's route builder and therefore should be stopped and removed based on lifecycle
+    private boolean wasUsedRouteBuilder;
+
+    @Inject
+    protected CamelContext context;
+
+    //------------------------ quarkus callbacks ---------------
+
+    /**
+     * Replacement of {@link #afterAll(ExtensionContext)} called from {@link AfterAllCallback#afterAll(QuarkusTestContext)}
+     */
+    protected void doAfterAll(QuarkusTestContext context) throws Exception {
+    }
+
+    /**
+     * Replacement of {@link #afterEach(ExtensionContext)} called from
+     * {@link AfterEachCallback#afterEach(QuarkusTestMethodContext)}
+     */
+    protected void doAfterEach(QuarkusTestMethodContext context) throws Exception {
+    }
+
+    /**
+     * Replacement of {@link #beforeAll(ExtensionContext)} called from {@link AfterConstructCallback#afterConstruct(Object)}
+     * Execution differs in case of <i>@TestInstance(TestInstance.Lifecycle.PER_METHOD)</i> in which case callback is called
+     * before each test (instead of {@link #beforeAll(ExtensionContext)}).
+     */
+    protected void doAfterConstruct() throws Exception {
+    }
+
+    /**
+     * Replacement of {@link #beforeEach(ExtensionContext)} called from
+     * {@link BeforeEachCallback#beforeEach(QuarkusTestMethodContext)}
+     */
+    protected void doBeforeEach(QuarkusTestMethodContext context) throws Exception {
+    }
+
+    /**
+     * Feel free to override this method for the sake of customizing the instance returned by this implementation.
+     * Do not create your own CamelContext instance, because there needs to exist just a single instance owned by
+     * Quarkus CDI container. There are checks in place that will make your tests fail if you do otherwise.
+     *
+     * @return           The context from Quarkus CDI container
+     * @throws Exception Overridden method has to throw the same Exception as superclass.
+     */
+    @Override
+    protected CamelContext createCamelContext() throws Exception {
+        return this.context;
+    }
+
+    /**
+     * The same functionality as {@link CamelTestSupport#bindToRegistry(Registry)}.
+     */
+    @Override
+    protected void bindToRegistry(Registry registry) throws Exception {
+        //CamelTestSupport has to use the same context as CamelQuarkusTestSupport
+        Assertions.assertEquals(context, super.context, "Different context found!");
+        super.bindToRegistry(registry);
+    }
+
+    /**
+     * The same functionality as {@link CamelTestSupport#postProcessTest()} .
+     */
+    @Override
+    protected void postProcessTest() throws Exception {
+        //CamelTestSupport has to use the same context as CamelQuarkusTestSupport
+        Assertions.assertEquals(context, super.context, "Different context found!");
+        super.postProcessTest();
+    }
+
+    /**
+     * The same functionality as {@link CamelTestSupport#context()} .
+     */
+    @Override
+    public CamelContext context() {
+        //CamelTestSupport has to use the same context as CamelQuarkusTestSupport
+        Assertions.assertEquals(context, super.context, "Different context found!");
+        return super.context();
+    }
+
+    /**
+     * This method is not called on Camel Quarkus because the `CamelRegistry` is created and owned by Quarkus CDI container.
+     * If you need to customize the registry upon creation, you may want to override {@link #createCamelContext()}
+     * in the following way:
+     *
+     * @Override
+     *           protected CamelContext createCamelContext() throws Exception {
+     *           CamelContext ctx = super.createCamelContext();
+     *           Registry registry = ctx.getRegistry();
+     *           // do something with the registry...
+     *           return ctx;
+     *           }
+     *
+     * @return   Never returns any result. UnsupportedOperationException is thrown instead.
+     */
+    @Override
+    protected final Registry createCamelRegistry() {
+        throw new UnsupportedOperationException("won't be executed.");
+    }
+
+    /**
+     * This method does nothing. All necessary tasks are performed in
+     * {@link BeforeEachCallback#beforeEach(QuarkusTestMethodContext)}
+     * Use {@link #doAfterConstruct()} instead of this method.
+     */
+    @Override
+    public final void beforeAll(ExtensionContext context) {
+        //replaced by quarkus callback (beforeEach)
+    }
+
+    /**
+     * This method does nothing. All tasks are performed in {@link BeforeEachCallback#beforeEach(QuarkusTestMethodContext)}
+     * Use {@link #doBeforeEach(QuarkusTestMethodContext)} instead of this method.
+     */
+    @Override
+    public final void beforeEach(ExtensionContext context) throws Exception {
+        //replaced by quarkus callback (beforeEach)
+    }
+
+    /**
+     * This method does nothing. All necessary tasks are performed in
+     * {@link BeforeEachCallback#beforeEach(QuarkusTestMethodContext)}
+     * Use {@link #doAfterAll(QuarkusTestContext)} instead of this method.
+     */
+    @Override
+    public final void afterAll(ExtensionContext context) {
+        //in camel-quarkus, junit5 uses different classloader, necessary code was moved into quarkus's callback
+    }
+
+    /**
+     * This method does nothing. All necessary tasks are performed in
+     * {@link BeforeEachCallback#beforeEach(QuarkusTestMethodContext)}
+     * Use {@link #doAfterEach(QuarkusTestMethodContext)} instead of this method.
+     */
+    @Override
+    public final void afterEach(ExtensionContext context) throws Exception {
+        //in camel-quarkus, junit5 uses different classloader, necessary code was moved into quarkus's callback
+    }
+
+    /**
+     * This method does nothing All necessary tasks are performed in
+     * {@link BeforeEachCallback#beforeEach(QuarkusTestMethodContext)}
+     * Use {@link #doAfterEach(QuarkusTestMethodContext)} instead of this method.
+     */
+    @Override
+    public final void afterTestExecution(ExtensionContext context) throws Exception {
+        //in camel-quarkus, junit5 uses different classloader, necessary code was moved into quarkus's callback
+    }
+
+    /**
+     * This method stops the Camel context. Be aware that on of the limitation that Quarkus brings is that context
+     * can not be started (lifecycle f the context is bound to the application) .
+     *
+     * @throws Exception
+     */
+    @Override
+    protected void stopCamelContext() throws Exception {
+        //context is started and stopped via quarkus lifecycle
+    }
+
+    /**
+     * Allows running of the CamelTestSupport child in the Quarkus application.
+     * Method is not intended to be overridden.
+     */
+    @Override
+    protected final void doQuarkusCheck() {
+        //can run on Quarkus
+    }
+
+    void internalAfterAll(QuarkusTestContext context) {
+        try {
+            doPostTearDown();
+            cleanupResources();
+        } catch (Exception e) {
+            // ignore
+        }
+    }
+
+    void internalBeforeAll(ExtensionContext context) {
+        super.beforeAll(context);
+    }
+
+    void internalBeforeEach(ExtensionContext context) throws Exception {
+        super.beforeEach(context);
+    }
+
+    /**
+     * Strategy to perform any pre setup, before {@link CamelContext} is created
+     * <p>
+     * Be aware that difference in lifecycle with Quarkus may require a special behavior.
+     * If this method is overridden, <i>super.doPreSetup()</i> has to be called.
+     * </p>
+     */
+    @Override
+    protected void doPreSetup() throws Exception {
+        if (isUseAdviceWith() || isUseDebugger()) {
+            ((FastCamelContext) context).suspend();
+        }
+        super.doPreSetup();
+    }
+
+    /**
+     * Strategy to perform any post setup after {@link CamelContext} is created
+     * <p>
+     * Be aware that difference in lifecycle with Quarkus may require a special behavior.
+     * If this method is overridden, <i>super.doPostSetup()</i> has to be called.
+     * </p>
+     */
+    @Override
+    protected void doPostSetup() throws Exception {
+        if (isUseAdviceWith() || isUseDebugger()) {
+            ((FastCamelContext) context).resume();
+            if (isUseDebugger()) {
+                ModelCamelContext mcc = context.adapt(ModelCamelContext.class);
+                List<RouteDefinition> rdfs = mcc.getRouteDefinitions();
+                //if context was suspended routes was not added, because it would trigger start of the context
+                // routes have to be added now
+                mcc.addRouteDefinitions(rdfs);
+            }
+        }
+        super.doPostSetup();
+    }
+
+    /**
+     * Internal disablement of the context stop functionality.
+     */
+    @Override
+    protected final void doStopCamelContext(CamelContext context, Service camelContextService) {
+        //don't stop
+    }
+
+    /**
+     * This method does nothing. The context starts together with Quarkus engine.
+     */
+    @Override
+    protected final void startCamelContext() {
+        //context has already started
+    }
+}
diff --git a/test-framework/junit5/src/main/resources/META-INF/services/io.quarkus.test.junit.callback.QuarkusTestAfterAllCallback b/test-framework/junit5/src/main/resources/META-INF/services/io.quarkus.test.junit.callback.QuarkusTestAfterAllCallback
new file mode 100644
index 0000000..23f8280
--- /dev/null
+++ b/test-framework/junit5/src/main/resources/META-INF/services/io.quarkus.test.junit.callback.QuarkusTestAfterAllCallback
@@ -0,0 +1 @@
+org.apache.camel.quarkus.test.AfterAllCallback
diff --git a/test-framework/junit5/src/main/resources/META-INF/services/io.quarkus.test.junit.callback.QuarkusTestAfterConstructCallback b/test-framework/junit5/src/main/resources/META-INF/services/io.quarkus.test.junit.callback.QuarkusTestAfterConstructCallback
new file mode 100644
index 0000000..5e84edb
--- /dev/null
+++ b/test-framework/junit5/src/main/resources/META-INF/services/io.quarkus.test.junit.callback.QuarkusTestAfterConstructCallback
@@ -0,0 +1 @@
+org.apache.camel.quarkus.test.AfterConstructCallback
diff --git a/test-framework/junit5/src/main/resources/META-INF/services/io.quarkus.test.junit.callback.QuarkusTestAfterEachCallback b/test-framework/junit5/src/main/resources/META-INF/services/io.quarkus.test.junit.callback.QuarkusTestAfterEachCallback
new file mode 100644
index 0000000..8749fd5
--- /dev/null
+++ b/test-framework/junit5/src/main/resources/META-INF/services/io.quarkus.test.junit.callback.QuarkusTestAfterEachCallback
@@ -0,0 +1 @@
+org.apache.camel.quarkus.test.AfterEachCallback
diff --git a/test-framework/junit5/src/main/resources/META-INF/services/io.quarkus.test.junit.callback.QuarkusTestBeforeEachCallback b/test-framework/junit5/src/main/resources/META-INF/services/io.quarkus.test.junit.callback.QuarkusTestBeforeEachCallback
new file mode 100644
index 0000000..0887c99
--- /dev/null
+++ b/test-framework/junit5/src/main/resources/META-INF/services/io.quarkus.test.junit.callback.QuarkusTestBeforeEachCallback
@@ -0,0 +1 @@
+org.apache.camel.quarkus.test.BeforeEachCallback
diff --git a/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/common/AbstractCallbacksTest.java b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/common/AbstractCallbacksTest.java
new file mode 100644
index 0000000..b1bcbcf
--- /dev/null
+++ b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/common/AbstractCallbacksTest.java
@@ -0,0 +1,272 @@
+/*
+ * 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.quarkus.test.common;
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.BiConsumer;
+import java.util.stream.Collectors;
+
+import io.quarkus.test.junit.callback.QuarkusTestContext;
+import io.quarkus.test.junit.callback.QuarkusTestMethodContext;
+import org.apache.camel.CamelContext;
+import org.apache.camel.Produce;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.quarkus.test.CamelQuarkusTestSupport;
+import org.apache.camel.quarkus.test.junit5.patterns.DebugJUnit5Test;
+import org.apache.camel.util.StopWatch;
+import org.jboss.logging.Logger;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public abstract class AbstractCallbacksTest extends CamelQuarkusTestSupport {
+
+    private static final Logger LOG = Logger.getLogger(DebugJUnit5Test.class);
+
+    public enum Callback {
+        postTearDown,
+        doSetup,
+        preSetup,
+        postSetup,
+        contextCreation,
+        afterAll,
+        afterConstruct,
+        afterEach,
+        beforeEach;
+    }
+
+    private final String testName;
+    private final String afterClassTestName;
+
+    @Produce("direct:start")
+    protected ProducerTemplate template;
+
+    public AbstractCallbacksTest(String testName, String afterClassTestName) {
+        this.testName = testName;
+        this.afterClassTestName = afterClassTestName;
+    }
+
+    @Override
+    protected CamelContext createCamelContext() throws Exception {
+        createTmpFile(testName, Callback.contextCreation);
+        createTmpFile(afterClassTestName, Callback.contextCreation);
+        return super.createCamelContext();
+    }
+
+    @Override
+    protected void doPreSetup() throws Exception {
+        createTmpFile(testName, Callback.preSetup);
+        createTmpFile(afterClassTestName, Callback.preSetup);
+        super.doPostSetup();
+    }
+
+    @Override
+    protected void doSetUp() throws Exception {
+        createTmpFile(testName, Callback.doSetup);
+        createTmpFile(afterClassTestName, Callback.doSetup);
+        super.doSetUp();
+    }
+
+    @Override
+    protected void doPostSetup() throws Exception {
+        createTmpFile(testName, Callback.postSetup);
+        createTmpFile(afterClassTestName, Callback.postSetup);
+        super.doPostSetup();
+    }
+
+    @Override
+    protected void doPostTearDown() throws Exception {
+        createTmpFile(testName, Callback.postTearDown);
+        createTmpFile(afterClassTestName, Callback.postTearDown);
+        super.doPostTearDown();
+    }
+
+    @Test
+    public void testMock() throws Exception {
+        getMockEndpoint("mock:result").expectedBodiesReceived("Hello World");
+        template.sendBody("direct:start", "Hello World");
+        assertMockEndpointsSatisfied();
+    }
+
+    @Test
+    public void testMock2() throws Exception {
+        getMockEndpoint("mock:result").expectedBodiesReceived("Hello World 2");
+        template.sendBody("direct:start", "Hello World 2");
+        assertMockEndpointsSatisfied();
+    }
+
+    @Test
+    public void testMock3() throws Exception {
+        getMockEndpoint("mock:result").expectedBodiesReceived("Hello World 2");
+        template.sendBody("direct:start", "Hello World 2");
+        assertMockEndpointsSatisfied();
+    }
+
+    @Override
+    protected RoutesBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                from("direct:start").to("mock:result");
+            }
+        };
+    }
+
+    @Override
+    protected void doAfterAll(QuarkusTestContext context) throws Exception {
+        createTmpFile(testName, Callback.afterAll);
+        createTmpFile(afterClassTestName, Callback.afterAll);
+        super.doAfterAll(context);
+    }
+
+    @Override
+    protected void doAfterConstruct() throws Exception {
+        createTmpFile(testName, Callback.afterConstruct);
+        createTmpFile(afterClassTestName, Callback.afterConstruct);
+        super.doAfterConstruct();
+    }
+
+    @Override
+    protected void doAfterEach(QuarkusTestMethodContext context) throws Exception {
+        createTmpFile(testName, Callback.afterEach);
+        createTmpFile(afterClassTestName, Callback.afterEach);
+        super.doAfterEach(context);
+    }
+
+    @Override
+    protected void doBeforeEach(QuarkusTestMethodContext context) throws Exception {
+        createTmpFile(testName, Callback.beforeEach);
+        createTmpFile(afterClassTestName, Callback.beforeEach);
+        super.doAfterConstruct();
+    }
+
+    static void assertCount(int expectedCount, Long count, Callback c, String testName) {
+        Assertions.assertEquals(expectedCount, count,
+                c.name() + " should be called exactly " + expectedCount + " times in " + testName);
+    }
+
+    static void testAfterAll(String testName, BiConsumer<Callback, Long> consumer) {
+        // we are called before doPostTearDown so lets wait for that to be
+        // called
+        Runnable r = () -> {
+            Map<AbstractCallbacksTest.Callback, Long> counts = new HashMap<>();
+            try {
+                StopWatch watch = new StopWatch();
+                while (watch.taken() < 5000) {
+                    checkCallbacks(Callback.values(), testName, counts);
+
+                    if (counts.size() == AbstractCallbacksTest.Callback.values().length) {
+                        break;
+                    } else {
+                        try {
+                            Thread.sleep(100);
+                        } catch (InterruptedException e) {
+                            break;
+                        }
+                    }
+                }
+            } finally {
+                LOG.info("Should only call postTearDown 1 time per test class, called: ");
+                for (Callback c : Callback.values()) {
+                    consumer.accept(c, counts.get(c));
+                }
+            }
+
+        };
+        Thread t = new Thread(r);
+        t.setDaemon(false);
+        t.setName("shouldTearDown checker");
+        t.start();
+    }
+
+    /**
+     * Return -1 if there is no file. Numer of passed test otherwise.
+     */
+    public static int testFromAnotherClass(String testName, BiConsumer<Callback, Long> consumer) {
+        int i = 0;
+        Map<AbstractCallbacksTest.Callback, Long> counts = new HashMap<>();
+        checkCallbacks(Callback.values(), testName, counts);
+        if (counts.size() == 0) {
+            return -1;
+        }
+        for (Callback c : Callback.values()) {
+            consumer.accept(c, counts.get(c));
+            i++;
+        }
+        return i;
+    }
+
+    private static void checkCallbacks(Callback[] values, String testName, Map<Callback, Long> counts) {
+        LOG.debug("Checking for callbacks called correctly");
+        try {
+            for (Callback c : values) {
+                long count = doesTmpFileExist(testName, c);
+                if (count > 0) {
+                    counts.put(c, count);
+                }
+            }
+        } catch (Exception e) {
+            //ignore
+        }
+    }
+
+    private static void createTmpFile(String testName, Callback callback) throws Exception {
+        Set<File> testDirs = Arrays.stream(Paths.get("target").toFile().listFiles())
+                .filter(f -> f.isDirectory() && f.getName().startsWith(testName))
+                .collect(Collectors.toSet());
+
+        Path tmpDir;
+        if (testDirs.size() == 1) {
+            tmpDir = testDirs.stream().findFirst().get().toPath();
+        } else if (testDirs.size() > 1) {
+            throw new RuntimeException();
+        } else {
+            tmpDir = Files.createTempDirectory(Paths.get("target"), testName);
+            tmpDir.toFile().deleteOnExit();
+        }
+
+        Path tmpFile = Files.createTempFile(tmpDir, callback.name(), ".log");
+        tmpFile.toFile().deleteOnExit();
+    }
+
+    private static long doesTmpFileExist(String testName, Callback callback) throws Exception {
+        //find test dir
+        Set<File> testDirs = Arrays.stream(Paths.get("target").toFile().listFiles())
+                .filter(f -> f.isDirectory() && f.getName().contains(testName))
+                .collect(Collectors.toSet());
+        if (testDirs.size() > 1) {
+            LOG.warn("There are more tmp folders for the Callback tests.");
+            return -1;
+        }
+        if (testDirs.isEmpty()) {
+            LOG.warn("There is no tmp folder for the Callback tests.");
+            return 0;
+        }
+
+        return Arrays.stream(testDirs.stream().findFirst().get().listFiles())
+                .filter(f -> f.getName().startsWith(callback.name()))
+                .count();
+    }
+}
diff --git a/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/common/AbstractSimpleMockTest.java b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/common/AbstractSimpleMockTest.java
new file mode 100644
index 0000000..bda1723
--- /dev/null
+++ b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/common/AbstractSimpleMockTest.java
@@ -0,0 +1,64 @@
+/*
+ * 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.quarkus.test.common;
+
+import io.quarkus.test.junit.QuarkusTest;
+import org.apache.camel.Produce;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.quarkus.test.CamelQuarkusTestSupport;
+import org.junit.jupiter.api.Test;
+
+@QuarkusTest
+public abstract class AbstractSimpleMockTest extends CamelQuarkusTestSupport {
+
+    @Produce("direct:start")
+    protected ProducerTemplate template;
+
+    private String msgToSend;
+    private String msgToExpect;
+
+    public AbstractSimpleMockTest(String msgToSend, String msgToExpect) {
+        this.msgToSend = msgToSend;
+        this.msgToExpect = msgToExpect;
+    }
+
+    public void setMsgToSend(String msgToSend) {
+        this.msgToSend = msgToSend;
+    }
+
+    @Test
+    public void testMock() throws Exception {
+        getMockEndpoint("mock:result").expectedBodiesReceived(msgToExpect);
+
+        template.sendBody("direct:start", msgToSend);
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Override
+    protected RoutesBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                from("direct:start").to("mock:result");
+            }
+        };
+    }
+
+}
diff --git a/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/common/CallbacksPerTestFalse01Test.java b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/common/CallbacksPerTestFalse01Test.java
new file mode 100644
index 0000000..54e0ff0
--- /dev/null
+++ b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/common/CallbacksPerTestFalse01Test.java
@@ -0,0 +1,76 @@
+/*
+ * 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.quarkus.test.common;
+
+import java.util.function.BiConsumer;
+
+import io.quarkus.test.junit.QuarkusTest;
+import io.quarkus.test.junit.TestProfile;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.TestInstance;
+
+// replaces CreateCamelContextPerTestTrueTest
+@QuarkusTest
+@TestInstance(TestInstance.Lifecycle.PER_METHOD)
+@TestProfile(CallbacksPerTestFalse01Test.class)
+public class CallbacksPerTestFalse01Test extends AbstractCallbacksTest {
+
+    public CallbacksPerTestFalse01Test() {
+        super(CallbacksPerTestFalse01Test.class.getSimpleName(), CallbacksPerTestFalse02Test.class.getSimpleName());
+    }
+
+    @AfterAll
+    public static void shouldTearDown() {
+        testAfterAll(CallbacksPerTestFalse01Test.class.getSimpleName(), createAssertionConsumer());
+    }
+
+    protected static BiConsumer<Callback, Long> createAssertionConsumer() {
+        return (callback, count) -> {
+            switch (callback) {
+            case doSetup:
+                assertCount(3, count, callback, CallbacksPerTestFalse01Test.class.getSimpleName());
+                break;
+            case contextCreation:
+                assertCount(3, count, callback, CallbacksPerTestFalse01Test.class.getSimpleName());
+                break;
+            case postSetup:
+                assertCount(3, count, callback, CallbacksPerTestFalse01Test.class.getSimpleName());
+                break;
+            case postTearDown:
+                assertCount(3, count, callback, CallbacksPerTestFalse01Test.class.getSimpleName());
+                break;
+            case preSetup:
+                assertCount(3, count, callback, CallbacksPerTestFalse01Test.class.getSimpleName());
+                break;
+            case afterAll:
+                assertCount(1, count, callback, CallbacksPerTestFalse01Test.class.getSimpleName());
+                break;
+            case afterConstruct:
+                assertCount(3, count, callback, CallbacksPerTestFalse01Test.class.getSimpleName());
+                break;
+            case afterEach:
+                assertCount(3, count, callback, CallbacksPerTestFalse01Test.class.getSimpleName());
+                break;
+            case beforeEach:
+                assertCount(3, count, callback, CallbacksPerTestFalse01Test.class.getSimpleName());
+                break;
+            default:
+                throw new IllegalArgumentException("Unknown callback type");
+            }
+        };
+    }
+}
diff --git a/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/common/CallbacksPerTestFalse02Test.java b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/common/CallbacksPerTestFalse02Test.java
new file mode 100644
index 0000000..f9fbb14
--- /dev/null
+++ b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/common/CallbacksPerTestFalse02Test.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.quarkus.test.common;
+
+import java.util.concurrent.TimeUnit;
+
+import io.quarkus.test.junit.QuarkusTest;
+import io.quarkus.test.junit.TestProfile;
+import org.hamcrest.Matchers;
+
+import static org.awaitility.Awaitility.await;
+
+// replaces CreateCamelContextPerTestTrueTest
+@QuarkusTest
+@TestProfile(CallbacksPerTestFalse01Test.class)
+public class CallbacksPerTestFalse02Test {
+
+    //    @Test
+    public void testAfter01Class() {
+
+        await().atMost(5, TimeUnit.SECONDS).until(() -> AbstractCallbacksTest.testFromAnotherClass(
+                CallbacksPerTestFalse02Test.class.getSimpleName(),
+                CallbacksPerTestFalse01Test.createAssertionConsumer()),
+                Matchers.is(AbstractCallbacksTest.Callback.values().length));
+
+    }
+}
diff --git a/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/common/CallbacksPerTestTrue01Test.java b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/common/CallbacksPerTestTrue01Test.java
new file mode 100644
index 0000000..54bcbfd
--- /dev/null
+++ b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/common/CallbacksPerTestTrue01Test.java
@@ -0,0 +1,76 @@
+/*
+ * 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.quarkus.test.common;
+
+import java.util.function.BiConsumer;
+
+import io.quarkus.test.junit.QuarkusTest;
+import io.quarkus.test.junit.TestProfile;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.TestInstance;
+
+// replaces CreateCamelContextPerTestTrueTest
+@QuarkusTest
+@TestInstance(TestInstance.Lifecycle.PER_CLASS)
+@TestProfile(CallbacksPerTestTrue01Test.class)
+public class CallbacksPerTestTrue01Test extends AbstractCallbacksTest {
+
+    public CallbacksPerTestTrue01Test() {
+        super(CallbacksPerTestTrue01Test.class.getSimpleName(), CallbacksPerTestTrue02Test.class.getSimpleName());
+    }
+
+    @AfterAll
+    public static void shouldTearDown() {
+        testAfterAll(CallbacksPerTestTrue01Test.class.getSimpleName(), createAssertionConsumer());
+    }
+
+    protected static BiConsumer<Callback, Long> createAssertionConsumer() {
+        return (callback, count) -> {
+            switch (callback) {
+            case doSetup:
+                assertCount(1, count, callback, CallbacksPerTestTrue01Test.class.getSimpleName());
+                break;
+            case contextCreation:
+                assertCount(1, count, callback, CallbacksPerTestTrue01Test.class.getSimpleName());
+                break;
+            case postSetup:
+                assertCount(1, count, callback, CallbacksPerTestTrue01Test.class.getSimpleName());
+                break;
+            case postTearDown:
+                assertCount(1, count, callback, CallbacksPerTestTrue01Test.class.getSimpleName());
+                break;
+            case preSetup:
+                assertCount(1, count, callback, CallbacksPerTestTrue01Test.class.getSimpleName());
+                break;
+            case afterAll:
+                assertCount(1, count, callback, CallbacksPerTestFalse01Test.class.getSimpleName());
+                break;
+            case afterConstruct:
+                assertCount(1, count, callback, CallbacksPerTestFalse01Test.class.getSimpleName());
+                break;
+            case afterEach:
+                assertCount(3, count, callback, CallbacksPerTestFalse01Test.class.getSimpleName());
+                break;
+            case beforeEach:
+                assertCount(3, count, callback, CallbacksPerTestFalse01Test.class.getSimpleName());
+                break;
+            default:
+                throw new IllegalArgumentException("Unknown callback type");
+            }
+        };
+    }
+}
diff --git a/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/common/CallbacksPerTestTrue02Test.java b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/common/CallbacksPerTestTrue02Test.java
new file mode 100644
index 0000000..777c3b9
--- /dev/null
+++ b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/common/CallbacksPerTestTrue02Test.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.quarkus.test.common;
+
+import java.util.concurrent.TimeUnit;
+
+import io.quarkus.test.junit.QuarkusTest;
+import io.quarkus.test.junit.TestProfile;
+import org.hamcrest.Matchers;
+import org.junit.jupiter.api.Test;
+
+import static org.awaitility.Awaitility.await;
+
+// replaces CreateCamelContextPerTestTrueTest
+@QuarkusTest
+@TestProfile(CallbacksPerTestTrue01Test.class)
+public class CallbacksPerTestTrue02Test {
+
+    @Test
+    public void testAfter01Class() {
+
+        await().atMost(5, TimeUnit.SECONDS).until(() -> AbstractCallbacksTest.testFromAnotherClass(
+                CallbacksPerTestTrue02Test.class.getSimpleName(),
+                CallbacksPerTestTrue01Test.createAssertionConsumer()),
+                Matchers.is(AbstractCallbacksTest.Callback.values().length));
+
+    }
+}
diff --git a/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/common/JupiterCallbackCorrectTest.java b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/common/JupiterCallbackCorrectTest.java
new file mode 100644
index 0000000..70adea1
--- /dev/null
+++ b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/common/JupiterCallbackCorrectTest.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.quarkus.test.common;
+
+import io.quarkus.test.junit.QuarkusTest;
+import org.junit.jupiter.api.BeforeEach;
+
+@QuarkusTest
+public class JupiterCallbackCorrectTest extends AbstractSimpleMockTest {
+
+    public JupiterCallbackCorrectTest() {
+        super("hello", "hi");
+    }
+
+    @BeforeEach
+    public void beforeEach() throws Exception {
+        setMsgToSend("hi");
+    }
+}
diff --git a/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/CamelTestSupportTest.java b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/CamelTestSupportTest.java
new file mode 100644
index 0000000..71caa86
--- /dev/null
+++ b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/CamelTestSupportTest.java
@@ -0,0 +1,80 @@
+/*
+ * 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.quarkus.test.junit5;
+
+import io.quarkus.test.junit.QuarkusTest;
+import io.quarkus.test.junit.TestProfile;
+import org.apache.camel.NoSuchEndpointException;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.quarkus.test.CamelQuarkusTestSupport;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+@QuarkusTest
+@TestProfile(CamelTestSupportTest.class)
+public class CamelTestSupportTest extends CamelQuarkusTestSupport {
+
+    @Override
+    @BeforeEach
+    public void setUp() throws Exception {
+        replaceRouteFromWith("routeId", "direct:start");
+        super.setUp();
+    }
+
+    @Test
+    public void replacesFromEndpoint() throws Exception {
+        getMockEndpoint("mock:result").expectedBodiesReceived("Hello World");
+
+        template.sendBody("direct:start", "Hello World");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Test
+    public void exceptionThrownWhenEndpointNotFoundAndNoCreate() {
+        assertThrows(NoSuchEndpointException.class, () -> {
+            getMockEndpoint("mock:bogus", false);
+        });
+    }
+
+    @Test
+    public void exceptionThrownWhenEndpointNotAMockEndpoint() {
+        assertThrows(NoSuchEndpointException.class, () -> {
+            getMockEndpoint("direct:something", false);
+        });
+    }
+
+    @Test
+    public void autoCreateNonExisting() {
+        MockEndpoint mock = getMockEndpoint("mock:bogus2", true);
+        assertNotNull(mock);
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                from("direct:something").id("routeId").to("mock:result");
+            }
+        };
+    }
+}
diff --git a/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/RouteFilterPatternExcludeTest.java b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/RouteFilterPatternExcludeTest.java
new file mode 100644
index 0000000..a8c573d
--- /dev/null
+++ b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/RouteFilterPatternExcludeTest.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.quarkus.test.junit5;
+
+import io.quarkus.test.junit.QuarkusTest;
+import io.quarkus.test.junit.TestProfile;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.model.Model;
+import org.apache.camel.quarkus.test.CamelQuarkusTestSupport;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+@QuarkusTest
+@TestProfile(RouteFilterPatternExcludeTest.class)
+public class RouteFilterPatternExcludeTest extends CamelQuarkusTestSupport {
+
+    @Override
+    public String getRouteFilterExcludePattern() {
+        return "bar*";
+    }
+
+    @Test
+    public void testRouteFilter() throws Exception {
+        assertEquals(1, context.getRoutes().size());
+        assertEquals(1, context.getExtension(Model.class).getRouteDefinitions().size());
+        assertEquals("foo", context.getExtension(Model.class).getRouteDefinitions().get(0).getId());
+
+        getMockEndpoint("mock:foo").expectedMessageCount(1);
+
+        template.sendBody("direct:foo", "Hello World");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                from("direct:foo").routeId("foo").to("mock:foo");
+
+                from("direct:bar").routeId("bar").to("mock:bar");
+            }
+        };
+    }
+
+}
diff --git a/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/RouteFilterPatternIncludeExcludeTest.java b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/RouteFilterPatternIncludeExcludeTest.java
new file mode 100644
index 0000000..a96a1e2
--- /dev/null
+++ b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/RouteFilterPatternIncludeExcludeTest.java
@@ -0,0 +1,69 @@
+/*
+ * 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.quarkus.test.junit5;
+
+import io.quarkus.test.junit.QuarkusTest;
+import io.quarkus.test.junit.TestProfile;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.model.Model;
+import org.apache.camel.quarkus.test.CamelQuarkusTestSupport;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+@QuarkusTest
+@TestProfile(RouteFilterPatternIncludeExcludeTest.class)
+public class RouteFilterPatternIncludeExcludeTest extends CamelQuarkusTestSupport {
+
+    @Override
+    public String getRouteFilterIncludePattern() {
+        return "foo*";
+    }
+
+    @Override
+    public String getRouteFilterExcludePattern() {
+        return "jms:*";
+    }
+
+    @Test
+    public void testRouteFilter() throws Exception {
+        assertEquals(1, context.getRoutes().size());
+        assertEquals(1, context.getExtension(Model.class).getRouteDefinitions().size());
+        assertEquals("foo", context.getExtension(Model.class).getRouteDefinitions().get(0).getId());
+
+        getMockEndpoint("mock:foo").expectedMessageCount(1);
+
+        template.sendBody("direct:foo", "Hello World");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                from("direct:foo").routeId("foo").to("mock:foo");
+
+                from("direct:bar").routeId("bar").to("mock:bar");
+
+                from("jms:beer").routeId("foolish").to("mock:beer");
+            }
+        };
+    }
+
+}
diff --git a/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/RouteFilterPatternIncludeTest.java b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/RouteFilterPatternIncludeTest.java
new file mode 100644
index 0000000..d293508
--- /dev/null
+++ b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/RouteFilterPatternIncludeTest.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.quarkus.test.junit5;
+
+import io.quarkus.test.junit.QuarkusTest;
+import io.quarkus.test.junit.TestProfile;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.model.Model;
+import org.apache.camel.quarkus.test.CamelQuarkusTestSupport;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+@QuarkusTest
+@TestProfile(RouteFilterPatternIncludeTest.class)
+public class RouteFilterPatternIncludeTest extends CamelQuarkusTestSupport {
+
+    @Override
+    public String getRouteFilterIncludePattern() {
+        return "foo*";
+    }
+
+    @Test
+    public void testRouteFilter() throws Exception {
+        assertEquals(1, context.getRoutes().size());
+        assertEquals(1, context.getExtension(Model.class).getRouteDefinitions().size());
+        assertEquals("foo", context.getExtension(Model.class).getRouteDefinitions().get(0).getId());
+
+        getMockEndpoint("mock:foo").expectedMessageCount(1);
+
+        template.sendBody("direct:foo", "Hello World");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                from("direct:foo").routeId("foo").to("mock:foo");
+
+                from("direct:bar").routeId("bar").to("mock:bar");
+            }
+        };
+    }
+
+}
diff --git a/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/AdviceWithLambdaTest.java b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/AdviceWithLambdaTest.java
new file mode 100644
index 0000000..ef19a48
--- /dev/null
+++ b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/AdviceWithLambdaTest.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.quarkus.test.junit5.patterns;
+
+import io.quarkus.test.junit.QuarkusTest;
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.AdviceWith;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.quarkus.test.CamelQuarkusTestSupport;
+import org.junit.jupiter.api.Test;
+
+@QuarkusTest
+public class AdviceWithLambdaTest extends CamelQuarkusTestSupport {
+
+    @Override
+    public boolean isUseAdviceWith() {
+        return true;
+    }
+
+    @Test
+    public void testAdviceWith() throws Exception {
+        getMockEndpoint("mock:result").expectedMessageCount(1);
+
+        // advice the route in one line
+        AdviceWith.adviceWith(context, "foo", a -> a.weaveAddLast().to("mock:result"));
+
+        template.sendBody("direct:start", "Bye World");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Override
+    protected RoutesBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                from("direct:start").routeId("foo").to("log:foo");
+            }
+        };
+    }
+}
diff --git a/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/DebugJUnit5Test.java b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/DebugJUnit5Test.java
new file mode 100644
index 0000000..6988d77
--- /dev/null
+++ b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/DebugJUnit5Test.java
@@ -0,0 +1,94 @@
+/*
+ * 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.quarkus.test.junit5.patterns;
+
+import io.quarkus.test.junit.QuarkusTest;
+import io.quarkus.test.junit.TestProfile;
+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.quarkus.test.CamelQuarkusTestSupport;
+import org.jboss.logging.Logger;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInstance;
+
+@QuarkusTest
+@TestInstance(TestInstance.Lifecycle.PER_CLASS)
+@TestProfile(DebugJUnit5Test.class)
+public class DebugJUnit5Test extends CamelQuarkusTestSupport {
+
+    private static final Logger LOG = Logger.getLogger(DebugJUnit5Test.class);
+
+    // START SNIPPET: e1
+    @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());
+    }
+    // END SNIPPET: e1
+
+    @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();
+    }
+
+    @Test
+    public void testTwo() throws Exception {
+        // set mock expectations
+        getMockEndpoint("mock:a").expectedMessageCount(2);
+        getMockEndpoint("mock:b").expectedMessageCount(2);
+
+        // send a message
+        template.sendBody("direct:start", "World");
+        template.sendBody("direct:start", "Camel");
+
+        // assert mocks
+        assertMockEndpointsSatisfied();
+    }
+
+    // START SNIPPET: e2
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                // this is the route we want to debug
+                from("direct:start").to("mock:a").transform(body().prepend("Hello ")).to("mock:b");
+            }
+        };
+    }
+    // END SNIPPET: e2
+}
diff --git a/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/DebugNoLazyTypeConverterTest.java b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/DebugNoLazyTypeConverterTest.java
new file mode 100644
index 0000000..f5a18ee
--- /dev/null
+++ b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/DebugNoLazyTypeConverterTest.java
@@ -0,0 +1,90 @@
+/*
+ * 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.quarkus.test.junit5.patterns;
+
+import io.quarkus.test.junit.QuarkusTest;
+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.quarkus.test.CamelQuarkusTestSupport;
+import org.jboss.logging.Logger;
+import org.junit.jupiter.api.Test;
+
+@QuarkusTest
+public class DebugNoLazyTypeConverterTest extends CamelQuarkusTestSupport {
+
+    private static final Logger LOG = Logger.getLogger(DebugNoLazyTypeConverterTest.class);
+
+    // START SNIPPET: e1
+    @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());
+    }
+    // END SNIPPET: e1
+
+    @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();
+    }
+
+    @Test
+    public void testTwo() throws Exception {
+        // set mock expectations
+        getMockEndpoint("mock:a").expectedMessageCount(2);
+        getMockEndpoint("mock:b").expectedMessageCount(2);
+
+        // send a message
+        template.sendBody("direct:start", "World");
+        template.sendBody("direct:start", "Camel");
+
+        // assert mocks
+        assertMockEndpointsSatisfied();
+    }
+
+    // START SNIPPET: e2
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                // this is the route we want to debug
+                from("direct:start").to("mock:a").transform(body().prepend("Hello ")).to("mock:b");
+            }
+        };
+    }
+    // END SNIPPET: e2
+}
diff --git a/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/DebugTest.java b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/DebugTest.java
new file mode 100644
index 0000000..665178c
--- /dev/null
+++ b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/DebugTest.java
@@ -0,0 +1,97 @@
+/*
+ * 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.quarkus.test.junit5.patterns;
+
+import io.quarkus.test.junit.QuarkusTest;
+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.quarkus.test.CamelQuarkusTestSupport;
+import org.jboss.logging.Logger;
+import org.junit.jupiter.api.Test;
+
+@QuarkusTest
+public class DebugTest extends CamelQuarkusTestSupport {
+
+    private static final Logger LOG = Logger.getLogger(DebugTest.class);
+
+    @Override
+    public boolean isUseAdviceWith() {
+        return true;
+    }
+
+    // START SNIPPET: e1
+    @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());
+    }
+    // END SNIPPET: e1
+
+    @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();
+    }
+
+    @Test
+    public void testTwo() throws Exception {
+
+        // set mock expectations
+        getMockEndpoint("mock:a").expectedMessageCount(2);
+        getMockEndpoint("mock:b").expectedMessageCount(2);
+
+        // send a message
+        template.sendBody("direct:start", "World");
+        template.sendBody("direct:start", "Camel");
+
+        // assert mocks
+        assertMockEndpointsSatisfied();
+    }
+
+    // START SNIPPET: e2
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                // this is the route we want to debug
+                from("direct:start").to("mock:a").transform(body().prepend("Hello ")).to("mock:b").routeId("foo");
+            }
+        };
+    }
+    // END SNIPPET: e2
+}
diff --git a/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/FilterCreateCamelContextPerClassTest.java b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/FilterCreateCamelContextPerClassTest.java
new file mode 100644
index 0000000..5e3d550
--- /dev/null
+++ b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/FilterCreateCamelContextPerClassTest.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.quarkus.test.junit5.patterns;
+
+import io.quarkus.test.junit.QuarkusTest;
+import io.quarkus.test.junit.TestProfile;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.quarkus.test.CamelQuarkusTestSupport;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInstance;
+
+/**
+ * Tests filtering using Camel Test
+ */
+// START SNIPPET: example
+@QuarkusTest
+@TestInstance(TestInstance.Lifecycle.PER_CLASS)
+@TestProfile(FilterCreateCamelContextPerClassTest.class)
+public class FilterCreateCamelContextPerClassTest extends CamelQuarkusTestSupport {
+
+    @Test
+    public void testSendMatchingMessage() throws Exception {
+        String expectedBody = "<matched/>";
+
+        getMockEndpoint("mock:result").expectedBodiesReceived(expectedBody);
+
+        template.sendBodyAndHeader("direct:start", expectedBody, "foo", "bar");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Test
+    public void testSendNotMatchingMessage() throws Exception {
+        getMockEndpoint("mock:result").expectedMessageCount(0);
+
+        template.sendBodyAndHeader("direct:start", "<notMatched/>", "foo", "notMatchedHeaderValue");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            public void configure() {
+                from("direct:start").filter(header("foo").isEqualTo("bar")).to("mock:result");
+            }
+        };
+    }
+}
diff --git a/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/FilterFluentTemplateTest.java b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/FilterFluentTemplateTest.java
new file mode 100644
index 0000000..a250c94
--- /dev/null
+++ b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/FilterFluentTemplateTest.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.quarkus.test.junit5.patterns;
+
+import io.quarkus.test.junit.QuarkusTest;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.FluentProducerTemplate;
+import org.apache.camel.Produce;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.quarkus.test.CamelQuarkusTestSupport;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests filtering using Camel Test
+ */
+// START SNIPPET: example
+// tag::example[]
+@QuarkusTest
+public class FilterFluentTemplateTest extends CamelQuarkusTestSupport {
+
+    @EndpointInject("mock:result")
+    protected MockEndpoint resultEndpoint;
+
+    @Produce("direct:startFluent")
+    protected FluentProducerTemplate fluentTemplate;
+
+    @Override
+    public boolean isDumpRouteCoverage() {
+        return true;
+    }
+
+    @Test
+    public void testSendMatchingMessage() throws Exception {
+        String expectedBody = "<matched/>";
+
+        resultEndpoint.expectedBodiesReceived(expectedBody);
+
+        fluentTemplate.withBody(expectedBody).withHeader("foo", "bar").send();
+
+        resultEndpoint.assertIsSatisfied();
+
+        resultEndpoint.reset();
+    }
+
+    @Test
+    public void testSendNotMatchingMessage() throws Exception {
+        resultEndpoint.expectedMessageCount(0);
+
+        fluentTemplate.withBody("<notMatched/>").withHeader("foo", "notMatchedHeaderValue").send();
+
+        resultEndpoint.assertIsSatisfied();
+
+        resultEndpoint.reset();
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            public void configure() {
+                from("direct:startFluent").filter(header("foo").isEqualTo("bar")).to("mock:result");
+            }
+        };
+    }
+}
+// end::example[]
+// END SNIPPET: example
diff --git a/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/FilterJUnit5Test.java b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/FilterJUnit5Test.java
new file mode 100644
index 0000000..24bbb4b
--- /dev/null
+++ b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/FilterJUnit5Test.java
@@ -0,0 +1,75 @@
+/*
+ * 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.quarkus.test.junit5.patterns;
+
+import io.quarkus.test.junit.QuarkusTest;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Produce;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.quarkus.test.CamelQuarkusTestSupport;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests filtering using Camel Test
+ */
+// START SNIPPET: example
+@QuarkusTest
+public class FilterJUnit5Test extends CamelQuarkusTestSupport {
+
+    @EndpointInject("mock:result")
+    protected MockEndpoint resultEndpoint;
+
+    @Produce("direct:start")
+    protected ProducerTemplate template;
+
+    @Test
+    public void testSendMatchingMessage() throws Exception {
+        String expectedBody = "<matched/>";
+
+        resultEndpoint.expectedBodiesReceived(expectedBody);
+
+        template.sendBodyAndHeader(expectedBody, "foo", "bar");
+
+        resultEndpoint.assertIsSatisfied();
+
+        resultEndpoint.reset();
+    }
+
+    @Test
+    public void testSendNotMatchingMessage() throws Exception {
+        resultEndpoint.expectedMessageCount(0);
+
+        template.sendBodyAndHeader("<notMatched/>", "foo", "notMatchedHeaderValue");
+
+        resultEndpoint.assertIsSatisfied();
+
+        resultEndpoint.reset();
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            public void configure() {
+                from("direct:start").filter(header("foo").isEqualTo("bar")).to("mock:result");
+            }
+        };
+    }
+
+}
+// END SNIPPET: example
diff --git a/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/FilterTest.java b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/FilterTest.java
new file mode 100644
index 0000000..feca9fc
--- /dev/null
+++ b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/FilterTest.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.quarkus.test.junit5.patterns;
+
+import io.quarkus.test.junit.QuarkusTest;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Produce;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.quarkus.test.CamelQuarkusTestSupport;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests filtering using Camel Test
+ */
+// START SNIPPET: example
+// tag::example[]
+@QuarkusTest
+public class FilterTest extends CamelQuarkusTestSupport {
+
+    @EndpointInject("mock:result")
+    protected MockEndpoint resultEndpoint;
+
+    @Produce("direct:start")
+    protected ProducerTemplate template;
+
+    @Override
+    public boolean isDumpRouteCoverage() {
+        return true;
+    }
+
+    @Test
+    public void testSendMatchingMessage() throws Exception {
+        String expectedBody = "<matched/>";
+
+        resultEndpoint.expectedBodiesReceived(expectedBody);
+
+        template.sendBodyAndHeader(expectedBody, "foo", "bar");
+
+        resultEndpoint.assertIsSatisfied();
+
+        resultEndpoint.reset();
+    }
+
+    @Test
+    public void testSendNotMatchingMessage() throws Exception {
+        resultEndpoint.expectedMessageCount(0);
+
+        template.sendBodyAndHeader("<notMatched/>", "foo", "notMatchedHeaderValue");
+
+        resultEndpoint.assertIsSatisfied();
+
+        resultEndpoint.reset();
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            public void configure() {
+                from("direct:start").filter(header("foo").isEqualTo("bar")).to("mock:result");
+            }
+        };
+    }
+}
+// end::example[]
+// END SNIPPET: example
diff --git a/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/GetMockEndpointTest.java b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/GetMockEndpointTest.java
new file mode 100644
index 0000000..09fe8a0
--- /dev/null
+++ b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/GetMockEndpointTest.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.quarkus.test.junit5.patterns;
+
+import io.quarkus.test.junit.QuarkusTest;
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.quarkus.test.CamelQuarkusTestSupport;
+import org.junit.jupiter.api.Test;
+
+@QuarkusTest
+public class GetMockEndpointTest extends CamelQuarkusTestSupport {
+
+    @Test
+    public void testMock() throws Exception {
+        getMockEndpoint("mock:result").expectedBodiesReceived("Hello World");
+
+        template.sendBody("direct:start", "Hello World");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Override
+    protected RoutesBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                from("direct:start").to("mock:result?failFast=false");
+            }
+        };
+    }
+
+}
diff --git a/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/IsMockEndpointsAndSkipJUnit5Test.java b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/IsMockEndpointsAndSkipJUnit5Test.java
new file mode 100644
index 0000000..e69b848
--- /dev/null
+++ b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/IsMockEndpointsAndSkipJUnit5Test.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.quarkus.test.junit5.patterns;
+
+import io.quarkus.test.junit.QuarkusTest;
+import io.quarkus.test.junit.TestProfile;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.seda.SedaEndpoint;
+import org.apache.camel.quarkus.test.CamelQuarkusTestSupport;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+// START SNIPPET: e1
+// tag::e1[]
+@QuarkusTest
+@TestProfile(IsMockEndpointsAndSkipJUnit5Test.class)
+public class IsMockEndpointsAndSkipJUnit5Test extends CamelQuarkusTestSupport {
+
+    @Override
+    public String isMockEndpointsAndSkip() {
+        // override this method and return the pattern for which endpoints to
+        // mock,
+        // and skip sending to the original endpoint.
+        return "direct:foo";
+    }
+
+    @Test
+    public void testMockEndpointAndSkip() throws Exception {
+        // notice we have automatic mocked the direct:foo endpoints and the name
+        // of the endpoints is "mock:uri"
+        getMockEndpoint("mock:result").expectedBodiesReceived("Hello World");
+        getMockEndpoint("mock:direct:foo").expectedMessageCount(1);
+
+        template.sendBody("direct:start", "Hello World");
+
+        assertMockEndpointsSatisfied();
+
+        // the message was not send to the direct:foo route and thus not sent to
+        // the seda endpoint
+        SedaEndpoint seda = context.getEndpoint("seda:foo", SedaEndpoint.class);
+        assertEquals(0, seda.getCurrentQueueSize());
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                from("direct:start").to("direct:foo").to("mock:result");
+
+                from("direct:foo").transform(constant("Bye World")).to("seda:foo");
+            }
+        };
+    }
+}
+// end::e1[]
+// END SNIPPET: e1
diff --git a/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/IsMockEndpointsFileTest.java b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/IsMockEndpointsFileTest.java
new file mode 100644
index 0000000..3088f11
--- /dev/null
+++ b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/IsMockEndpointsFileTest.java
@@ -0,0 +1,73 @@
+/*
+ * 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.quarkus.test.junit5.patterns;
+
+import io.quarkus.test.junit.QuarkusTest;
+import org.apache.camel.Exchange;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.quarkus.test.CamelQuarkusTestSupport;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.apache.camel.test.junit5.TestSupport.deleteDirectory;
+
+@QuarkusTest
+public class IsMockEndpointsFileTest extends CamelQuarkusTestSupport {
+
+    @Override
+    @BeforeEach
+    public void setUp() throws Exception {
+        deleteDirectory("target/input");
+        deleteDirectory("target/messages");
+        super.setUp();
+    }
+
+    @Override
+    public String isMockEndpoints() {
+        // override this method and return the pattern for which endpoints to
+        // mock.
+        return "file:target*";
+    }
+
+    @Test
+    public void testMockFileEndpoints() throws Exception {
+        // notice we have automatic mocked all endpoints and the name of the
+        // endpoints is "mock:uri"
+        MockEndpoint camel = getMockEndpoint("mock:file:target/messages/camel");
+        camel.expectedMessageCount(1);
+
+        MockEndpoint other = getMockEndpoint("mock:file:target/messages/others");
+        other.expectedMessageCount(1);
+
+        template.sendBodyAndHeader("file:target/input", "Hello Camel", Exchange.FILE_NAME, "camel.txt");
+        template.sendBodyAndHeader("file:target/input", "Hello World", Exchange.FILE_NAME, "world.txt");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                from("file:target/input").choice().when(bodyAs(String.class).contains("Camel")).to("file:target/messages/camel")
+                        .otherwise().to("file:target/messages/others");
+            }
+        };
+    }
+}
diff --git a/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/IsMockEndpointsJUnit5Test.java b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/IsMockEndpointsJUnit5Test.java
new file mode 100644
index 0000000..cffc66f
--- /dev/null
+++ b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/IsMockEndpointsJUnit5Test.java
@@ -0,0 +1,76 @@
+/*
+ * 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.quarkus.test.junit5.patterns;
+
+import io.quarkus.test.junit.QuarkusTest;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.quarkus.test.CamelQuarkusTestSupport;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+// START SNIPPET: e1
+// tag::e1[]
+@QuarkusTest
+public class IsMockEndpointsJUnit5Test extends CamelQuarkusTestSupport {
+
+    @Override
+    public String isMockEndpoints() {
+        // override this method and return the pattern for which endpoints to
+        // mock.
+        // use * to indicate all
+        return "*";
+    }
+
+    @Test
+    public void testMockAllEndpoints() throws Exception {
+        // notice we have automatic mocked all endpoints and the name of the
+        // endpoints is "mock:uri"
+        getMockEndpoint("mock:direct:start").expectedBodiesReceived("Hello World");
+        getMockEndpoint("mock:direct:foo").expectedBodiesReceived("Hello World");
+        getMockEndpoint("mock:log:foo").expectedBodiesReceived("Bye World");
+        getMockEndpoint("mock:result").expectedBodiesReceived("Bye World");
+
+        template.sendBody("direct:start", "Hello World");
+
+        assertMockEndpointsSatisfied();
+
+        // additional test to ensure correct endpoints in registry
+        assertNotNull(context.hasEndpoint("direct:start"));
+        assertNotNull(context.hasEndpoint("direct:foo"));
+        assertNotNull(context.hasEndpoint("log:foo"));
+        assertNotNull(context.hasEndpoint("mock:result"));
+        // all the endpoints was mocked
+        assertNotNull(context.hasEndpoint("mock:direct:start"));
+        assertNotNull(context.hasEndpoint("mock:direct:foo"));
+        assertNotNull(context.hasEndpoint("mock:log:foo"));
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                from("direct:start").to("direct:foo").to("log:foo").to("mock:result");
+
+                from("direct:foo").transform(constant("Bye World"));
+            }
+        };
+    }
+}
+// end::e1[]
+// END SNIPPET: e1
diff --git a/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/IsMockEndpointsTest.java b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/IsMockEndpointsTest.java
new file mode 100644
index 0000000..a74fdbd
--- /dev/null
+++ b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/IsMockEndpointsTest.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.quarkus.test.junit5.patterns;
+
+import io.quarkus.test.junit.QuarkusTest;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.quarkus.test.CamelQuarkusTestSupport;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+@QuarkusTest
+public class IsMockEndpointsTest extends CamelQuarkusTestSupport {
+
+    @Override
+    public String isMockEndpoints() {
+        return "*";
+    }
+
+    @Test
+    public void testMockAllEndpoints() throws Exception {
+        getMockEndpoint("mock:direct:start").expectedBodiesReceived("Hello World");
+        getMockEndpoint("mock:direct:foo").expectedBodiesReceived("Hello World");
+        getMockEndpoint("mock:log:foo").expectedBodiesReceived("Bye World");
+        getMockEndpoint("mock:result").expectedBodiesReceived("Bye World");
+
+        template.sendBody("direct:start", "Hello World");
+
+        assertMockEndpointsSatisfied();
+
+        // additional test to ensure correct endpoints in registry
+        assertNotNull(context.hasEndpoint("direct:start"));
+        assertNotNull(context.hasEndpoint("direct:foo"));
+        assertNotNull(context.hasEndpoint("log:foo"));
+        assertNotNull(context.hasEndpoint("mock:result"));
+        // all the endpoints was mocked
+        assertNotNull(context.hasEndpoint("mock:direct:start"));
+        assertNotNull(context.hasEndpoint("mock:direct:foo"));
+        assertNotNull(context.hasEndpoint("mock:log:foo"));
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                from("direct:start").to("direct:foo").to("log:foo").to("mock:result");
+
+                from("direct:foo").transform(constant("Bye World"));
+            }
+        };
+    }
+}
diff --git a/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/MockEndpointFailNoHeaderTest.java b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/MockEndpointFailNoHeaderTest.java
new file mode 100644
index 0000000..59392ad
--- /dev/null
+++ b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/MockEndpointFailNoHeaderTest.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.test.junit5.patterns;
+
+import io.quarkus.test.junit.QuarkusTest;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Produce;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.quarkus.test.CamelQuarkusTestSupport;
+import org.junit.jupiter.api.Test;
+
+@QuarkusTest
+public class MockEndpointFailNoHeaderTest extends CamelQuarkusTestSupport {
+
+    @EndpointInject("mock:result")
+    protected MockEndpoint resultEndpoint;
+
+    @Produce("direct:start")
+    protected ProducerTemplate template;
+
+    @Override
+    public boolean isDumpRouteCoverage() {
+        return true;
+    }
+
+    @Test
+    public void withHeaderTestCase() throws InterruptedException {
+        String expectedBody = "<matched/>";
+        resultEndpoint.expectedHeaderReceived("foo", "bar");
+        template.sendBodyAndHeader(expectedBody, "foo", "bar");
+        resultEndpoint.assertIsSatisfied();
+    }
+
+    @Test
+    public void noHeaderTestCase() throws InterruptedException {
+        resultEndpoint.expectedHeaderReceived("foo", "bar");
+        resultEndpoint.setResultWaitTime(1); // speedup test
+        resultEndpoint.assertIsNotSatisfied();
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            public void configure() {
+                from("direct:start").filter(header("foo").isEqualTo("bar")).to("mock:result");
+            }
+        };
+    }
+}
diff --git a/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/MyProduceBean.java b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/MyProduceBean.java
new file mode 100644
index 0000000..45ec336
--- /dev/null
+++ b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/MyProduceBean.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.quarkus.test.junit5.patterns;
+
+import org.apache.camel.Produce;
+
+/**
+ *
+ */
+public class MyProduceBean {
+
+    @Produce("mock:result")
+    MySender sender;
+
+    public void doSomething(String body) {
+        sender.send(body);
+    }
+}
diff --git a/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/MySender.java b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/MySender.java
new file mode 100644
index 0000000..f0d1331
--- /dev/null
+++ b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/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.quarkus.test.junit5.patterns;
+
+/**
+ *
+ */
+public interface MySender {
+
+    void send(String body);
+}
diff --git a/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/ProduceBeanTest.java b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/ProduceBeanTest.java
new file mode 100644
index 0000000..fef74d3
--- /dev/null
+++ b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/ProduceBeanTest.java
@@ -0,0 +1,45 @@
+/*
+ * 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.quarkus.test.junit5.patterns;
+
+import io.quarkus.test.junit.QuarkusTest;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.quarkus.test.CamelQuarkusTestSupport;
+import org.junit.jupiter.api.Test;
+
+@QuarkusTest
+public class ProduceBeanTest extends CamelQuarkusTestSupport {
+
+    @Test
+    public void testProduceBean() throws Exception {
+        getMockEndpoint("mock:result").expectedMessageCount(1);
+
+        template.sendBody("direct:start", "Hello World");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                from("direct:start").bean(MyProduceBean.class, "doSomething");
+            }
+        };
+    }
+}
diff --git a/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/RouteBuilderConfigureExceptionTest.java b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/RouteBuilderConfigureExceptionTest.java
new file mode 100644
index 0000000..cfb26bd
--- /dev/null
+++ b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/RouteBuilderConfigureExceptionTest.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.test.junit5.patterns;
+
+import io.quarkus.test.junit.QuarkusTest;
+import org.apache.camel.Predicate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.quarkus.test.CamelQuarkusTestSupport;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.fail;
+
+@QuarkusTest
+public class RouteBuilderConfigureExceptionTest extends CamelQuarkusTestSupport {
+
+    private Predicate iAmNull;
+
+    @Override
+    @BeforeEach
+    public void setUp() {
+        try {
+            super.setUp();
+            fail("Should have thrown exception");
+        } catch (Exception e) {
+            // expected
+        }
+    }
+
+    @Test
+    public void testFoo() {
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            public void configure() {
+                from("direct:start").choice().when(iAmNull).to("mock:dead");
+            }
+        };
+    }
+}
diff --git a/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/RouteProcessorDumpRouteCoverageTest.java b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/RouteProcessorDumpRouteCoverageTest.java
new file mode 100644
index 0000000..a986b29
--- /dev/null
+++ b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/RouteProcessorDumpRouteCoverageTest.java
@@ -0,0 +1,74 @@
+/*
+ * 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.quarkus.test.junit5.patterns;
+
+import io.quarkus.test.junit.QuarkusTest;
+import io.quarkus.test.junit.TestProfile;
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.quarkus.test.CamelQuarkusTestSupport;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInfo;
+import org.junit.jupiter.api.TestReporter;
+
+import static org.apache.camel.test.junit5.TestSupport.assertFileExists;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+@QuarkusTest
+@TestProfile(RouteProcessorDumpRouteCoverageTest.class)
+public class RouteProcessorDumpRouteCoverageTest extends CamelQuarkusTestSupport {
+
+    @Override
+    public boolean isDumpRouteCoverage() {
+        return true;
+    }
+
+    @Test
+    public void testProcessorJunit5() {
+        String out = template.requestBody("direct:start", "Hello World", String.class);
+        assertEquals("Bye World", out);
+    }
+
+    @Test
+    public void testProcessorJunit5WithTestParameterInjection(TestInfo info, TestReporter testReporter) {
+        assertNotNull(info);
+        assertNotNull(testReporter);
+        String out = template.requestBody("direct:start", "Hello World", String.class);
+        assertEquals("Bye World", out);
+    }
+
+    @AfterAll
+    public static void checkDumpFilesCreatedAfterTests() {
+        // should create that file when test is done
+        assertFileExists("target/camel-route-coverage/RouteProcessorDumpRouteCoverageTest-testProcessorJunit5.xml");
+        assertFileExists(
+                "target/camel-route-coverage/RouteProcessorDumpRouteCoverageTest-testProcessorJunit5WithTestParameterInjection.xml");
+    }
+
+    @Override
+    protected RoutesBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                from("direct:start").process(exchange -> exchange.getMessage().setBody("Bye World"));
+            }
+        };
+    }
+
+}
diff --git a/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/SimpleMockEndpointsTest.java b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/SimpleMockEndpointsTest.java
new file mode 100644
index 0000000..54553ac
--- /dev/null
+++ b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/SimpleMockEndpointsTest.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.quarkus.test.junit5.patterns;
+
+import io.quarkus.test.junit.QuarkusTest;
+import org.apache.camel.Produce;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.quarkus.test.CamelQuarkusTestSupport;
+import org.junit.jupiter.api.Test;
+
+@QuarkusTest
+public class SimpleMockEndpointsTest extends CamelQuarkusTestSupport {
+
+    @Produce("direct:start")
+    protected ProducerTemplate template;
+
+    @Override
+    public String isMockEndpointsAndSkip() {
+        return "seda:queue";
+    }
+
+    @Test
+    public void testMockAndSkip() throws Exception {
+        getMockEndpoint("mock:seda:queue").expectedBodiesReceived("Bye Camel");
+
+        template.sendBody("seda:start", "Camel");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Override
+    protected RoutesBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                from("seda:start").transform(simple("Bye ${body}")).to("seda:queue");
+            }
+        };
+    }
+
+}
diff --git a/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/SimpleNotifyBuilderTest.java b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/SimpleNotifyBuilderTest.java
new file mode 100644
index 0000000..5cd5729
--- /dev/null
+++ b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/SimpleNotifyBuilderTest.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.quarkus.test.junit5.patterns;
+
+import java.util.concurrent.TimeUnit;
+
+import io.quarkus.test.junit.QuarkusTest;
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.NotifyBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.quarkus.test.CamelQuarkusTestSupport;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+@QuarkusTest
+public class SimpleNotifyBuilderTest extends CamelQuarkusTestSupport {
+
+    @Test
+    public void testNotifyBuilder() {
+        NotifyBuilder notify = new NotifyBuilder(context).from("seda:start").wereSentTo("seda:queue").whenDone(10).create();
+
+        for (int i = 0; i < 10; i++) {
+            template.sendBody("seda:start", "Camel" + i);
+        }
+
+        boolean matches = notify.matches(10, TimeUnit.SECONDS);
+        assertTrue(matches);
+    }
+
+    @Override
+    protected RoutesBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                from("seda:start").transform(simple("Bye ${body}")).to("seda:queue");
+            }
+        };
+    }
+
+}
diff --git a/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/SimpleWeaveAddMockLastTest.java b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/SimpleWeaveAddMockLastTest.java
new file mode 100644
index 0000000..0eb21ca
--- /dev/null
+++ b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/SimpleWeaveAddMockLastTest.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.test.junit5.patterns;
+
+import io.quarkus.test.junit.QuarkusTest;
+import io.quarkus.test.junit.TestProfile;
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.AdviceWith;
+import org.apache.camel.builder.AdviceWithRouteBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.model.Model;
+import org.apache.camel.quarkus.test.CamelQuarkusTestSupport;
+import org.junit.jupiter.api.Test;
+
+@QuarkusTest
+@TestProfile(SimpleWeaveAddMockLastTest.class)
+public class SimpleWeaveAddMockLastTest extends CamelQuarkusTestSupport {
+
+    public boolean isUseAdviceWith() {
+        return true;
+    }
+
+    @Test
+    public void testWeaveAddMockLast() throws Exception {
+        AdviceWith.adviceWith(context.getExtension(Model.class).getRouteDefinitions().get(0), context,
+                new AdviceWithRouteBuilder() {
+                    @Override
+                    public void configure() {
+                        weaveAddLast().to("mock:result");
+                    }
+                });
+        context.start();
+
+        getMockEndpoint("mock:result").expectedBodiesReceived("Bye Camel");
+
+        template.sendBody("seda:start", "Camel");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Override
+    protected RoutesBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                from("seda:start").transform(simple("Bye ${body}")).to("seda:queue");
+            }
+        };
+    }
+
+}
diff --git a/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/UseOverridePropertiesWithPropertiesComponentTest.java b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/UseOverridePropertiesWithPropertiesComponentTest.java
new file mode 100644
index 0000000..5e51698
--- /dev/null
+++ b/test-framework/junit5/src/test/java/org/apache/camel/quarkus/test/junit5/patterns/UseOverridePropertiesWithPropertiesComponentTest.java
@@ -0,0 +1,79 @@
+/*
+ * 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.quarkus.test.junit5.patterns;
+
+import java.util.Properties;
+
+import io.quarkus.test.junit.QuarkusTest;
+import io.quarkus.test.junit.TestProfile;
+import org.apache.camel.builder.AdviceWith;
+import org.apache.camel.builder.AdviceWithRouteBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.model.ModelCamelContext;
+import org.apache.camel.quarkus.test.CamelQuarkusTestSupport;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+@QuarkusTest
+@TestProfile(UseOverridePropertiesWithPropertiesComponentTest.class)
+public class UseOverridePropertiesWithPropertiesComponentTest extends CamelQuarkusTestSupport {
+
+    @Override
+    public boolean isUseAdviceWith() {
+        return true;
+    }
+
+    @BeforeEach
+    public void doSomethingBefore() throws Exception {
+        AdviceWithRouteBuilder mocker = new AdviceWithRouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                replaceFromWith("direct:sftp");
+
+                interceptSendToEndpoint("file:*").skipSendToOriginalEndpoint().to("mock:file");
+            }
+        };
+        AdviceWith.adviceWith(this.context.adapt(ModelCamelContext.class).getRouteDefinition("myRoute"), this.context, mocker);
+    }
+
+    @Override
+    protected Properties useOverridePropertiesWithPropertiesComponent() {
+        Properties pc = new Properties();
+        pc.put("ftp.username", "scott");
+        pc.put("ftp.password", "tiger");
+        return pc;
+    }
+
+    @Test
+    public void testOverride() throws Exception {
+        getMockEndpoint("mock:file").expectedMessageCount(1);
+
+        template.sendBody("direct:sftp", "Hello World");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            public void configure() {
+                from("ftp:somepath?username={{ftp.username}}&password={{ftp.password}}").routeId("myRoute")
+                        .to("file:target/out");
+            }
+        };
+    }
+}
diff --git a/test-framework/pom.xml b/test-framework/pom.xml
new file mode 100644
index 0000000..b9399b6
--- /dev/null
+++ b/test-framework/pom.xml
@@ -0,0 +1,69 @@
+<?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="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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.quarkus</groupId>
+        <artifactId>camel-quarkus-build-parent</artifactId>
+        <version>2.12.0-SNAPSHOT</version>
+        <relativePath>../poms/build-parent/pom.xml</relativePath>
+    </parent>
+
+    <artifactId>camel-quarkus-test-framework</artifactId>
+    <packaging>pom</packaging>
+
+    <name>Camel Quarkus :: Test Framework :: Parent</name>
+    <description>Ancillary modules required by some tests. Hosted outside the integration-tests directory
+        so that we can keep a flat hierarchy in the integration-tests directory.
+    </description>
+
+    <modules>
+        <module>junit5</module>
+        <module>junit5-extension-tests</module>
+    </modules>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>io.quarkus</groupId>
+                <artifactId>quarkus-bom</artifactId>
+                <version>${quarkus.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.camel.quarkus</groupId>
+                <artifactId>camel-quarkus-bom</artifactId>
+                <version>${project.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.camel.quarkus</groupId>
+                <artifactId>camel-quarkus-bom-test</artifactId>
+                <version>${project.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+</project>