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

jamesnetherton pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git


The following commit(s) were added to refs/heads/main by this push:
     new b95bc88278d Split the testing user guide into separate pages
b95bc88278d is described below

commit b95bc88278dd11c4b5607211e7fc8eb5038379f8
Author: James Netherton <[email protected]>
AuthorDate: Tue Oct 20 07:08:10 2026 +0100

    Split the testing user guide into separate pages
---
 docs/modules/ROOT/nav.adoc                         |   3 +
 .../modules/ROOT/pages/migration-guide/3.36.0.adoc |   2 +-
 docs/modules/ROOT/pages/user-guide/testing.adoc    | 734 +--------------------
 .../testing/camel-quarkus-test-support.adoc        | 364 ++++++++++
 .../user-guide/testing/camel-quarkus-test.adoc     | 209 ++++++
 .../user-guide/testing/external-services.adoc      | 152 +++++
 6 files changed, 734 insertions(+), 730 deletions(-)

diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc
index d26f3b3ef15..648e78b8233 100644
--- a/docs/modules/ROOT/nav.adoc
+++ b/docs/modules/ROOT/nav.adoc
@@ -9,6 +9,9 @@
 ** xref:user-guide/native-mode.adoc[Native mode]
 ** xref:user-guide/command-mode.adoc[Command mode]
 ** xref:user-guide/testing.adoc[Testing]
+*** xref:user-guide/testing/external-services.adoc[External services]
+*** xref:user-guide/testing/camel-quarkus-test.adoc[Annotation based testing]
+*** xref:user-guide/testing/camel-quarkus-test-support.adoc[CamelTestSupport 
style]
 ** xref:user-guide/security-model.adoc[Security model]
 ** xref:user-guide/examples.adoc[Examples]
 ** xref:user-guide/kubernetes.adoc[Kubernetes]
diff --git a/docs/modules/ROOT/pages/migration-guide/3.36.0.adoc 
b/docs/modules/ROOT/pages/migration-guide/3.36.0.adoc
index 42b144cd30a..7dd3c68d896 100644
--- a/docs/modules/ROOT/pages/migration-guide/3.36.0.adoc
+++ b/docs/modules/ROOT/pages/migration-guide/3.36.0.adoc
@@ -60,4 +60,4 @@ This is particularly useful when different tests in the same 
class need differen
 
 Advice modifications are now automatically cleaned up between test methods to 
prevent interference between tests. This ensures that each test starts with a 
clean route state.
 
-For more details, see the 
xref:user-guide/testing.adoc#_using_advicewith[Testing guide].
+For more details, see the 
xref:user-guide/testing/camel-quarkus-test-support.adoc#_using_advicewith[Testing
 guide].
diff --git a/docs/modules/ROOT/pages/user-guide/testing.adoc 
b/docs/modules/ROOT/pages/user-guide/testing.adoc
index cac4a378638..25386d005ce 100644
--- a/docs/modules/ROOT/pages/user-guide/testing.adoc
+++ b/docs/modules/ROOT/pages/user-guide/testing.adoc
@@ -7,7 +7,11 @@ Before going deeper into the subject, it is strongly advised 
to read xref:user-g
 When it comes to testing a route in the context of Quarkus, the recommended 
approach is to write local integration tests.
 This has the advantage of covering both JVM and native mode.
 
-xref:#_cameltestsupport_style_of_testing[`CamelTestSupport`] style testing can 
also be used. Note that it can only work in JVM mode.
+The following pages cover further testing topics:
+
+* xref:user-guide/testing/external-services.adoc[Testing with external 
services]
+* xref:user-guide/testing/camel-quarkus-test.adoc[Annotation based testing 
with `@CamelQuarkusTest`] (JVM mode only)
+* xref:user-guide/testing/camel-quarkus-test-support.adoc[`CamelTestSupport` 
style of testing] (JVM mode only)
 
 == A test running in JVM mode
 
@@ -74,731 +78,3 @@ must take one or more of the following forms:
 * If a container image was created during the build, then a container is 
started so that tests can be executed against it.
 
 For more information about `QuarkusIntegrationTest` see the 
https://quarkus.io/guides/getting-started-testing#quarkus-integration-test[Quarkus
 testing guide].
-
-== Testing with external services
-
-=== Testcontainers
-
-Sometimes your application needs to access an external service such as a 
message broker, database, etc.
-If a container image is available for the service of interest, 
https://www.testcontainers.org/[Testcontainers]
-can be used to start and stop these services for testing.
-
-For the application to work properly, it is often essential to pass the 
connection configuration data
-(host, port, user, password, etc. of the remote service) to the application 
before it starts.
-In the Quarkus ecosystem, `QuarkusTestResourceLifecycleManager` serves this 
purpose.
-
-You can start one or more containers in the `start()` method
-and return the connection configuration in the form of a `Map`, where the key 
is the name of a configuration property and the value is the property value.
-The entries of this map are then passed to the application either via command 
line (`-Dkey=value`) in native mode,
-or through a special MicroProfile configuration provider in JVM mode.
-Note that these settings have a higher precedence than the settings in 
`application.properties` file.
-
-[source,java]
-----
-import java.util.Map;
-import java.util.HashMap;
-
-import io.quarkus.test.common.QuarkusTestResourceLifecycleManager;
-import org.testcontainers.containers.GenericContainer;
-import org.testcontainers.containers.wait.strategy.Wait;
-
-public class MyTestResource implements QuarkusTestResourceLifecycleManager {
-
-    private GenericContainer<?> myContainer;
-
-    @Override
-    public Map<String, String> start() {
-        // Start the needed container(s)
-        myContainer = new 
GenericContainer(DockerImageName.parse("my/image:1.0.0"))
-                .withExposedPorts(1234)
-                .waitingFor(Wait.forListeningPort());
-
-        myContainer.start();
-
-        // Pass the configuration to the application under test
-        // You can also pass camel component property names / values to 
automatically configure Camel components
-        return new HashMap<>() {{
-                put("my-container.host", container.getHost());
-                put("my-container.port", "" + container.getMappedPort(1234));
-        }};
-    }
-
-    @Override
-    public void stop() {
-        // Stop the needed container(s)
-        myContainer.stop();
-    }
-}
-----
-
-The defined test resource needs to be referenced from the test classes with 
`@QuarkusTestResource` as shown below:
-
-[source,java]
-----
-import io.quarkus.test.common.QuarkusTestResource;
-import io.quarkus.test.junit.QuarkusTest;
-
-@QuarkusTest
-@QuarkusTestResource(MyTestResource.class)
-class MyTest {
-   ...
-}
-----
-
-More information can be found in the 
https://quarkus.io/guides/getting-started-testing#quarkus-test-resource[Quarkus 
testing guide]. Refer to Camel Quarkus source tree for a 
https://github.com/apache/camel-quarkus/blob/main/integration-tests/google-storage/src/test/java/org/apache/camel/quarkus/component/google/storage/it/GoogleStorageTestResource.java[complete
 example].
-
-=== WireMock
-
-It is sometimes useful to stub HTTP interactions with third party services & 
APIs so that tests do not have to connect to live endpoints, as this can incur 
costs and the service may not always be 100% available or reliable.
-
-An excellent tool for mocking & recording HTTP interactions is 
http://wiremock.org/[WireMock]. It is used extensively throughout the Camel 
Quarkus test suite for various component extensions. Here follows a typical 
workflow
-for setting up WireMock.
-
-First set up the WireMock server. Note that it is important to configure the 
Camel component under test to pass any HTTP interactions through the WireMock 
proxy. This is usually achieved by configuring a component property
-that determines the API endpoint URL. Sometimes things are less 
straightforward and some extra work is required to configure the API client 
library, as was the case for 
https://github.com/apache/camel-quarkus/blob/main/integration-tests/twilio/src/main/java/org/apache/camel/quarkus/component/twilio/it/TwilioResource.java#L83[Twilio].
-
-[source,java]
-----
-import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
-import static com.github.tomakehurst.wiremock.client.WireMock.get;
-import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
-import static 
com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import com.github.tomakehurst.wiremock.WireMockServer;
-
-import io.quarkus.test.common.QuarkusTestResourceLifecycleManager;
-
-public class WireMockTestResource implements 
QuarkusTestResourceLifecycleManager {
-
-    private WireMockServer server;
-
-    @Override
-    public Map<String, String> start() {
-        // Setup & start the server
-        server = new WireMockServer(
-            wireMockConfig().dynamicPort()
-        );
-        server.start();
-
-        // Stub an HTTP endpoint. Note that WireMock also supports a record 
and playback mode
-        // https://wiremock.org/docs/record-playback/
-        server.stubFor(
-            get(urlEqualTo("/api/greeting"))
-                .willReturn(aResponse()
-                    .withHeader("Content-Type", "application/json")
-                    .withBody("{\"message\": \"Hello World\"}")));
-
-        // Ensure the camel component API client passes requests through the 
WireMock proxy
-        Map<String, String> conf = new HashMap<>();
-        conf.put("camel.component.foo.server-url", server.baseUrl());
-        return conf;
-    }
-
-    @Override
-    public void stop() {
-        if (server != null) {
-            server.stop();
-        }
-    }
-}
-----
-
-Finally, ensure your test class has the `@QuarkusTestResource` annotation with 
the appropriate test resource class specified as the value. The WireMock server 
will be started before all tests are
-executed and will be shut down when all tests are finished.
-
-[source,java]
-----
-import io.quarkus.test.common.QuarkusTestResource;
-import io.quarkus.test.junit.QuarkusTest;
-
-@QuarkusTest
-@QuarkusTestResource(WireMockTestResource.class)
-class MyTest {
-   ...
-}
-----
-
-More examples of WireMock usage can be found in the Camel Quarkus integration 
test source tree such as in the 
https://github.com/apache/camel-quarkus/blob/main/integration-tests/validator/src/test/java/org/apache/camel/quarkus/component/validator/it/ValidatorTestResource.java[validator
 tests].
-
-=== Citrus Testing Framework
-
-The https://citrusframework.org/[Citrus Testing Framework] provides advanced 
integration testing capabilities for Camel Quarkus applications.
-For detailed information about using Citrus with Quarkus test support, see 
xref:manual::integration-test.adoc#_quarkus_test_support[Integration Testing 
with Citrus] in the Apache Camel documentation.
-
-== Annotation based testing with `@CamelQuarkusTest`
-
-`@CamelQuarkusTest` configures Camel specific test features with annotation 
attributes, without extending a base class.
-It implies `@QuarkusTest`.
-
-IMPORTANT: `@CamelQuarkusTest` only works in JVM mode.
-
-To use `@CamelQuarkusTest`, add `camel-quarkus-junit` as a test scoped 
dependency to your application.
-
-[source,xml]
-----
-<dependency>
-    <groupId>org.apache.camel.quarkus</groupId>
-    <artifactId>camel-quarkus-junit</artifactId>
-    <scope>test</scope>
-</dependency>
-----
-
-Everything declared on `@CamelQuarkusTest` applies to the whole test class.
-It is set up before the first test method runs and undone after the last one.
-`MockEndpoint` instances are reset after each test method.
-
-=== Test routes
-
-Routes for a test class are declared with `routes`.
-They are added before the first test method and removed after the last one.
-Route builder classes declared in a `@CamelQuarkusTest` class, or listed in 
`routes`, are never discovered as application routes.
-
-`CamelContext`, `ProducerTemplate`, `FluentProducerTemplate` and 
`ConsumerTemplate` can be injected with `@Inject`, and endpoints with 
`@EndpointInject`.
-
-[source,java]
-----
-@CamelQuarkusTest(routes = GreetingTest.Routes.class)
-class GreetingTest {
-
-    @Inject
-    ProducerTemplate template;
-
-    @EndpointInject("mock:result")
-    MockEndpoint result;
-
-    @Test
-    void greets() throws Exception {
-        result.expectedBodiesReceived("Hello World");
-        template.sendBody("direct:start", "World");
-        result.assertIsSatisfied();
-    }
-
-    public static class Routes extends RouteBuilder {
-        @Override
-        public void configure() {
-            from("direct:start").transform().simple("Hello 
${body}").to("mock:result");
-        }
-    }
-}
-----
-
-=== Advising application routes
-
-Advice for the test class is declared with `advices`, and route consumers are 
replaced with `replaceRouteFromWith`.
-
-[source,java]
-----
-@CamelQuarkusTest(
-        advices = @AdviceRoute(route = "my-kafka-route", advice = 
KafkaRouteTest.StubKafka.class),
-        replaceRouteFromWith = "my-timer-route=direct:trigger")
-class KafkaRouteTest {
-
-    static class StubKafka extends AdviceWithRouteBuilder {
-        @Override
-        public void configure() {
-            
weaveByToUri("kafka:output-topic*").replace().to("mock:kafka-stub");
-        }
-    }
-}
-----
-
-Advice for a single test method is applied with `CamelTestHelper`, which can 
be injected into the test class.
-It is undone after the test method.
-
-[source,java]
-----
-@CamelQuarkusTest
-class MyRouteTest {
-
-    @Inject
-    CamelTestHelper helper;
-
-    @Test
-    void withMock() throws Exception {
-        helper.adviceRoute("my-route", route -> 
route.weaveByToUri("kafka:*").replace().to("mock:kafka"));
-        // ...
-    }
-}
-----
-
-`CamelTestHelper` also provides `getMockEndpoint`, `resetMocks` and 
`startRouteDefinitions`.
-
-=== Replacing beans in the Camel registry
-
-Fields and no-arg methods annotated with `@ReplaceInRegistry` are bound to the 
Camel registry, using the member name as the bean name.
-The previous bindings are restored after the last test method.
-The beans are bound before the routes declared with `routes` are added. 
Application routes already exist at that point, as do the routes declared with 
`routes` in <<_shared_mode_and_isolated_mode,isolated mode>>, so routes that 
look up a bean when they are created do not use the replacement.
-Beans provided by CDI cannot be replaced this way. Use 
https://quarkus.io/guides/getting-started-testing#mock-support[`@InjectMock` or 
`QuarkusMock`] for those.
-
-[source,java]
-----
-@CamelQuarkusTest
-class GreeterTest {
-
-    @ReplaceInRegistry
-    Greeter greeter = new FakeGreeter();
-}
-----
-
-=== Shared mode and isolated mode
-
-By default, a test class shares the application with the other test classes of 
the module, and its routes are already started when the test class begins.
-Some features need to act before routes are created. They are only available 
when the test class owns its application, which is called isolated mode.
-
-A test class runs in isolated mode when it is annotated with `@TestProfile` 
and no other `@CamelQuarkusTest` class uses the same test profile.
-The usual way is for the test class to be its own test profile, in which case 
it must be public.
-
-[source,java]
-----
-@CamelQuarkusTest(mockEndpointsAndSkip = "kafka:*")
-@TestProfile(OrdersTest.class)
-public class OrdersTest implements QuarkusTestProfile {
-}
-----
-
-Using a feature that is only available in isolated mode fails the test build.
-
-[cols="2,1,1"]
-|===
-| Feature | Shared mode | Isolated mode
-
-| `routes`, `advices`, `replaceRouteFromWith`, `@ReplaceInRegistry`
-| Yes
-| Yes
-
-| `mockEndpoints`, `mockEndpointsAndSkip`, `stubEndpoints`
-| No
-| Yes
-
-| `autoStartupExclude`
-| No
-| Yes
-
-| `@ProvidesBreakpoint`
-| No
-| Yes
-
-| `dumpRouteCoverage`, `dumpRoute`, `shutdownTimeout`
-| Yes
-| Yes
-|===
-
-In isolated mode, `advices` and `replaceRouteFromWith` are applied before 
routes are created.
-
-=== Debugging, route coverage and route dumps
-
-A `public static` no-arg method annotated with `@ProvidesBreakpoint` and 
returning `org.apache.camel.spi.Breakpoint` enables the Camel debugger with 
that breakpoint.
-
-`dumpRouteCoverage = true` writes route coverage to 
`target/camel-route-coverage` after each test method. It requires 
`camel-quarkus-management`.
-
-`dumpRoute` writes the routes to `target/camel-route-dump` after each test 
method, in `xml` or `yaml` format.
-It requires `camel-quarkus-xml-io-dsl` for `xml`, and `camel-quarkus-yaml-io` 
for `yaml`.
-
-=== Continuous testing
-
-Continuous testing only detects test classes annotated with `@QuarkusTest`, or 
with annotations declared in the test sources that are meta-annotated with 
`@QuarkusTest`.
-To run `@CamelQuarkusTest` classes in continuous testing, annotate them with 
`@QuarkusTest` as well.
-
-[source,java]
-----
-@QuarkusTest
-@CamelQuarkusTest(routes = GreetingTest.Routes.class)
-class GreetingTest {
-}
-----
-
-=== Migrating from `CamelQuarkusTestSupport`
-
-[cols="1,1"]
-|===
-| `CamelQuarkusTestSupport` | `@CamelQuarkusTest`
-
-| `createRouteBuilder()`
-| `routes`. The routes apply to the whole test class. Test methods that need 
different routes belong in separate test classes.
-
-| `isMockEndpoints()`, `isMockEndpointsAndSkip()`
-| `mockEndpoints`, `mockEndpointsAndSkip`. These require 
<<_shared_mode_and_isolated_mode,isolated mode>>, including when only the 
routes declared with `routes` are mocked.
-
-| `adviceRoute()`
-| `CamelTestHelper.adviceRoute()` or `advices`
-
-| `getMockEndpoint()`
-| `@EndpointInject` or `CamelTestHelper.getMockEndpoint()`
-
-| `@BindToRegistry`, `bindToRegistry()`
-| `@ReplaceInRegistry` or CDI producers
-
-| `isDumpRouteCoverage()`
-| `dumpRouteCoverage`
-
-| `doBeforeEach()`, `doAfterEach()`, `doAfterConstruct()`, `doAfterAll()`
-| JUnit `@BeforeEach`, `@AfterEach`, `@BeforeAll`, `@AfterAll`
-|===
-
-== `CamelTestSupport` style of testing
-
-If you used Camel standalone or on other runtimes before, you may know 
`CamelTestSupport` already.
-The original `CamelTestSupport` class is not well suited to Quarkus, so 
there's an extended Quarkus friendly version called `CamelQuarkusTestSupport`.
-
-> IMPORTANT: `CamelQuarkusTestSupport` only works in JVM mode. If you need to 
test in native mode, then use one of the alternate test strategies described 
above.
-
-To use `CamelQuarkusTestSupport`, you must add `camel-quarkus-junit` as a test 
scoped dependency to your application.
-
-[source,xml]
-----
-<dependency>
-    <groupId>org.apache.camel.quarkus</groupId>
-    <artifactId>camel-quarkus-junit</artifactId>
-    <scope>test</scope>
-</dependency>
-----
-
-=== Customizing the `CamelContext` for testing
-
-You can customize the `CamelContext` for testing with 
https://quarkus.io/guides/config-reference#profiles[configuration profiles], 
CDI beans, observers, 
https://quarkus.io/guides/getting-started-testing#mock-support[mocks] etc.
-You can also override the `createCamelContext` method and interact directly 
with the `CamelContext`.
-
-IMPORTANT: When using `createCamelContext` you *MUST NOT*  instantiate and 
return a new `CamelContext`. Instead, invoke `super.createCamelContext()` and 
modify the returned `CamelContext` as needed.
-Failing to follow this rule will result in an exception being thrown.
-
-[source,java]
-----
-@QuarkusTest
-class SimpleTest extends CamelQuarkusTestSupport {
-
-    @Override
-    protected CamelContext createCamelContext() throws Exception {
-        // Must call super to get a handle on the application scoped 
CamelContext
-        CamelContext context = super.createCamelContext();
-        // Apply customizations
-        context.setTracing(true);
-        // Return the modified CamelContext
-        return context;
-    }
-}
-----
-
-=== Configuring routes for testing
-
-Any classes that extend `RouteBuilder` in your application will have their 
routes automatically added to the `CamelContext`.
-Similarly, any XML or YAML routes configured from 
`camel.main.routes-include-pattern` will also be loaded.
-
-This may not always be desirable for your tests.
-You control which routes get loaded at test time with configuration properties:
-
-* `quarkus.camel.routes-discovery.include-patterns`
-* `quarkus.camel.routes-discovery.exclude-patterns`,
-* `camel.main.routes-include-pattern`
-* `camel.main.routes-exclude-pattern`.
-
-You can also define test specific routes per test class by overriding 
`createRouteBuilder`:
-
-[source,java]
-----
-@QuarkusTest
-class SimpleTest extends CamelQuarkusTestSupport {
-    @Test
-    void testGreeting() {
-        MockEndpoint mockEndpoint = getMockEndpoint("mock:result");
-        mockEndpoint.expectedBodiesReceived("Hello World");
-
-        template.sendBody("direct:start", "World");
-
-        mockEndpoint.assertIsSatisfied();
-    }
-
-    @Override
-    protected RoutesBuilder createRouteBuilder() throws Exception {
-        return new RouteBuilder() {
-            @Override
-            public void configure() throws Exception {
-                from("direct:start")
-                    .transform().simple("Hello ${body}")
-                    .to("mock:result");
-            }
-        };
-    }
-}
-----
-
-=== CamelContext test lifecycle
-
-One of the main differences in `CamelQuarkusTestSupport` compared to 
`CamelTestSupport` is how the `CamelContext` lifecycle is managed.
-
-On Camel Quarkus, a single `CamelContext` is created for you automatically by 
the runtime.
-By default, this `CamelContext` is shared among all tests and remains started 
for the duration of the entire test suite execution.
-
-This can potentially have some unintended side effects for your tests.
-If you need to have the `CamelContext` restarted between tests, then you can 
create a custom 
https://quarkus.io/guides/getting-started-testing#testing_different_profiles[test
 profile], which will force the application under test to be restarted.
-
-For example, to define a test profile:
-
-[source,java]
-----
-@QuarkusTest
-class MyTestProfile implements QuarkusTestProfile {
-    ...
-}
-----
-
-Then reference it on the test class with `@TestProfile`:
-
-[source,java]
-----
-// @TestProfile will trigger the application to be restarted
-@TestProfile(MyTestProfile.class)
-@QuarkusTest
-class SimpleTest extends CamelQuarkusTestSupport {
-    ...
-}
-----
-
-NOTE: You cannot manually restart the `CamelContext` by invoking its `stop()` 
and `start()` methods. This will result in an exception.
-
-=== Examples
-
-==== Simple `RouteBuilder` and test class
-
-Simple `RouteBuilder`:
-
-[source,java]
-----
-public class MyRoutes extends RouteBuilder {
-    @Override
-    public void configure() {
-        from("direct:start")
-            .transform().simple("Hello ${body}")
-            .to("mock:result");
-    }
-}
-----
-
-Test sending a message payload to the `direct:start` endpoint:
-
-[source,java]
-----
-@QuarkusTest
-class SimpleTest extends CamelQuarkusTestSupport {
-    @Test
-    void testGreeting() {
-        MockEndpoint mockEndpoint = getMockEndpoint("mock:result");
-        mockEndpoint.expectedBodiesReceived("Hello World");
-
-        template.sendBody("direct:start", "World");
-
-        mockEndpoint.assertIsSatisfied();
-    }
-}
-----
-
-==== Using `AdviceWith`
-
-xref:manual::advice-with.adoc[AdviceWith] allows you to modify routes at 
runtime for testing purposes - replacing endpoints, adding interceptors, or 
changing route behavior without modifying production code.
-
-===== Advising existing application routes
-
-The recommended pattern is:
-
-1. Define routes in your *application code* (src/main/java)
-2. Use `AdviceWith` to modify these *existing* routes in your tests
-
-[source,java]
-----
-// Application code: src/main/java/com/example/MyRoutes.java
-public class MyRoutes extends RouteBuilder {
-    @Override
-    public void configure() {
-        from("kafka:input-topic").routeId("my-kafka-route")
-            .to("kafka:output-topic")
-            .to("mock:result");
-    }
-}
-
-// Test code: src/test/java/com/example/MyRoutesTest.java
-@QuarkusTest
-class MyRoutesTest extends CamelQuarkusTestSupport {
-    @BeforeEach
-    public void beforeEach() throws Exception {
-        // Advise the application route
-        AdviceWith.adviceWith(this.context, "my-kafka-route", route -> {
-            
route.weaveByToUri("kafka:output-topic*").replace().to("mock:kafka-stub");
-        });
-    }
-
-    @Test
-    void testRoute() throws Exception {
-        MockEndpoint stub = getMockEndpoint("mock:kafka-stub");
-        stub.expectedMessageCount(1);
-
-        template.sendBody("kafka:input-topic", "test");
-
-        stub.assertIsSatisfied();
-    }
-}
-----
-
-WARNING: Advising routes created via `createRouteBuilder()` in tests can lead 
to unpredictable behavior.
-
-===== Apply advice in `@BeforeEach` or `doBeforeEach`
-
-When all tests in a class need the same advice, apply it in `@BeforeEach` or 
override `doBeforeEach`:
-
-[source,java]
-----
-@QuarkusTest
-class SimpleTest extends CamelQuarkusTestSupport {
-    @BeforeEach
-    public void beforeEach() throws Exception {
-        // Apply advice to EXISTING application route
-        AdviceWith.adviceWith(this.context, "advisedRoute", route -> {
-            route.replaceFromWith("direct:replaced");
-        });
-        // Routes that aren't advised are automatically started after this 
method completes
-    }
-
-    @Test
-    void testAdvisedRoute() throws Exception {
-        MockEndpoint mockEndpoint = getMockEndpoint("mock:result");
-        mockEndpoint.expectedBodiesReceived("Hello World");
-
-        template.sendBody("direct:replaced", "World");
-
-        mockEndpoint.assertIsSatisfied();
-    }
-}
-----
-
-Routes that aren't advised are automatically started after `@BeforeEach` or 
`doBeforeEach` completes. Advice modifications are automatically cleaned up 
between test methods
-
-===== Per-test-method advice using `adviceRoute()`
-
-When you need *different* advice in each test method, use the `adviceRoute()` 
helper method which handles route lifecycle (stop, advice, start) automatically:
-
-[source,java]
-----
-@QuarkusTest
-class PerMethodAdviceTest extends CamelQuarkusTestSupport {
-    @Test
-    void testWithMockOutput() throws Exception {
-        // Apply advice specific to this test on EXISTING application route
-        adviceRoute("my-route", route -> {
-            
route.weaveByToUri("kafka:output*").replace().to("mock:kafka-stub");
-        });
-
-        MockEndpoint stub = getMockEndpoint("mock:kafka-stub");
-        stub.expectedMessageCount(1);
-
-        template.sendBody("kafka:input", "test message");
-
-        stub.assertIsSatisfied();
-    }
-
-    @Test
-    void testWithDifferentAdvice() throws Exception {
-        // Different advice for this test on the same EXISTING route
-        adviceRoute("my-route", route -> {
-            route.weaveByToUri("kafka:output*").replace()
-                .transform(simple("MODIFIED: ${body}"))
-                .to("mock:result");
-        });
-
-        // ... different test assertions
-    }
-}
-----
-
-===== Advice patterns
-
-IMPORTANT: When using `weaveByToUri()`, `weaveByType()`, or similar methods, 
use specific patterns rather than wildcards to avoid unintentionally matching 
endpoints from the main application or other routes.
-
-For example, instead of:
-[source,java]
-----
-// Matches ALL Kafka endpoints in the context
-route.weaveByToUri("kafka:*").replace().to("mock:result");
-----
-
-Use specific endpoint URIs:
-[source,java]
-----
-// Only matches the specific endpoint you intend to advise
-route.weaveByToUri("kafka:my-output-topic*").replace().to("mock:result");
-----
-
-Or use IDs for even more precision:
-[source,java]
-----
-// Uses ID for exact matching
-route.weaveById("kafkaProducer").replace().to("mock:result");
-----
-
-Wildcard patterns like `kafka:*`, `http:*`, or `direct:*` will match **all** 
endpoints of that type throughout the entire `CamelContext`, including routes 
from your main application that the test may not need to modify. This can cause 
unexpected test failures and interference between tests.
-
-===== Advice cleanup between tests
-
-Advice modifications are automatically cleaned up between test methods to 
prevent interference. This ensures that:
-
-* Each test starts with a clean route state
-* Advice from one test doesn't affect subsequent tests
-* Tests remain independent and can run in any order
-
-=== Limitations
-
-==== Test lifecycle methods inherited from `CamelTestSupport`
-
-`CamelQuarkusTestSupport` inherits some test lifecycle methods from 
`CamelTestSupport`. However, they should not be used and instead are replaced 
with equivalent methods in `CamelQuarkusTestSupport`.
-
-|===
-|CamelTestSupport lifecycle methods |CamelQuarkusTestSupport equivalent
-
-|`afterAll`
-|`doAfterAll`
-
-|`afterEach`, `afterTestExecution`
-|`doAfterEach`
-
-|`beforeAll`
-|`doAfterConstruct`
-
-|`beforeEach`
-|`doBeforeEach`
-|===
-
-==== Creating a custom Camel registry is not supported
-
-The `CamelQuarkusTestSupport` implementation of `createCamelRegistry` will 
throw `UnsupportedOperationException`.
-
-If you need to bind or unbind objects to the Camel registry, then you can do 
it by one of the following methods.
-
-* Produce named CDI beans
-+
-[source,java]
-----
-public class MyBeanProducers {
-    @Produces
-    @Named("myBean")
-    public MyBean createMyBean() {
-        return new MyBean();
-    }
-}
-----
-+
-* Override `createCamelContext` (see example above) and invoke 
`camelContext.getRegistry().bind("foo", fooBean)`
-* Use the `@BindToRegistry` annotation
-+
-[source,java]
-----
-@QuarkusTest
-class SimpleTest extends CamelQuarkusTestSupport {
-    @BindToRegistry("myBean")
-    MyBean myBean = new MyBean();
-}
-----
-+
-+
-
-NOTE: Beans bound to the Camel registry from individual test classes, will 
persist for the duration of the test suite execution.
-This could have unintended consequences, depending on your test expectations. 
You can use test profiles to restart the `CamelContext` to avoid this.
diff --git 
a/docs/modules/ROOT/pages/user-guide/testing/camel-quarkus-test-support.adoc 
b/docs/modules/ROOT/pages/user-guide/testing/camel-quarkus-test-support.adoc
new file mode 100644
index 00000000000..6f11063b720
--- /dev/null
+++ b/docs/modules/ROOT/pages/user-guide/testing/camel-quarkus-test-support.adoc
@@ -0,0 +1,364 @@
+= `CamelTestSupport` style of testing
+
+If you used Camel standalone or on other runtimes before, you may know 
`CamelTestSupport` already.
+The original `CamelTestSupport` class is not well suited to Quarkus, so 
there's an extended Quarkus friendly version called `CamelQuarkusTestSupport`.
+
+> IMPORTANT: `CamelQuarkusTestSupport` only works in JVM mode. If you need to 
test in native mode, then use one of the alternate test strategies described in 
the xref:user-guide/testing.adoc[Testing] guide.
+
+To use `CamelQuarkusTestSupport`, you must add `camel-quarkus-junit` as a test 
scoped dependency to your application.
+
+[source,xml]
+----
+<dependency>
+    <groupId>org.apache.camel.quarkus</groupId>
+    <artifactId>camel-quarkus-junit</artifactId>
+    <scope>test</scope>
+</dependency>
+----
+
+== Customizing the `CamelContext` for testing
+
+You can customize the `CamelContext` for testing with 
https://quarkus.io/guides/config-reference#profiles[configuration profiles], 
CDI beans, observers, 
https://quarkus.io/guides/getting-started-testing#mock-support[mocks] etc.
+You can also override the `createCamelContext` method and interact directly 
with the `CamelContext`.
+
+IMPORTANT: When using `createCamelContext` you *MUST NOT*  instantiate and 
return a new `CamelContext`. Instead, invoke `super.createCamelContext()` and 
modify the returned `CamelContext` as needed.
+Failing to follow this rule will result in an exception being thrown.
+
+[source,java]
+----
+@QuarkusTest
+class SimpleTest extends CamelQuarkusTestSupport {
+
+    @Override
+    protected CamelContext createCamelContext() throws Exception {
+        // Must call super to get a handle on the application scoped 
CamelContext
+        CamelContext context = super.createCamelContext();
+        // Apply customizations
+        context.setTracing(true);
+        // Return the modified CamelContext
+        return context;
+    }
+}
+----
+
+== Configuring routes for testing
+
+Any classes that extend `RouteBuilder` in your application will have their 
routes automatically added to the `CamelContext`.
+Similarly, any XML or YAML routes configured from 
`camel.main.routes-include-pattern` will also be loaded.
+
+This may not always be desirable for your tests.
+You control which routes get loaded at test time with configuration properties:
+
+* `quarkus.camel.routes-discovery.include-patterns`
+* `quarkus.camel.routes-discovery.exclude-patterns`,
+* `camel.main.routes-include-pattern`
+* `camel.main.routes-exclude-pattern`.
+
+You can also define test specific routes per test class by overriding 
`createRouteBuilder`:
+
+[source,java]
+----
+@QuarkusTest
+class SimpleTest extends CamelQuarkusTestSupport {
+    @Test
+    void testGreeting() {
+        MockEndpoint mockEndpoint = getMockEndpoint("mock:result");
+        mockEndpoint.expectedBodiesReceived("Hello World");
+
+        template.sendBody("direct:start", "World");
+
+        mockEndpoint.assertIsSatisfied();
+    }
+
+    @Override
+    protected RoutesBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start")
+                    .transform().simple("Hello ${body}")
+                    .to("mock:result");
+            }
+        };
+    }
+}
+----
+
+== CamelContext test lifecycle
+
+One of the main differences in `CamelQuarkusTestSupport` compared to 
`CamelTestSupport` is how the `CamelContext` lifecycle is managed.
+
+On Camel Quarkus, a single `CamelContext` is created for you automatically by 
the runtime.
+By default, this `CamelContext` is shared among all tests and remains started 
for the duration of the entire test suite execution.
+
+This can potentially have some unintended side effects for your tests.
+If you need to have the `CamelContext` restarted between tests, then you can 
create a custom 
https://quarkus.io/guides/getting-started-testing#testing_different_profiles[test
 profile], which will force the application under test to be restarted.
+
+For example, to define a test profile:
+
+[source,java]
+----
+@QuarkusTest
+class MyTestProfile implements QuarkusTestProfile {
+    ...
+}
+----
+
+Then reference it on the test class with `@TestProfile`:
+
+[source,java]
+----
+// @TestProfile will trigger the application to be restarted
+@TestProfile(MyTestProfile.class)
+@QuarkusTest
+class SimpleTest extends CamelQuarkusTestSupport {
+    ...
+}
+----
+
+NOTE: You cannot manually restart the `CamelContext` by invoking its `stop()` 
and `start()` methods. This will result in an exception.
+
+== Examples
+
+=== Simple `RouteBuilder` and test class
+
+Simple `RouteBuilder`:
+
+[source,java]
+----
+public class MyRoutes extends RouteBuilder {
+    @Override
+    public void configure() {
+        from("direct:start")
+            .transform().simple("Hello ${body}")
+            .to("mock:result");
+    }
+}
+----
+
+Test sending a message payload to the `direct:start` endpoint:
+
+[source,java]
+----
+@QuarkusTest
+class SimpleTest extends CamelQuarkusTestSupport {
+    @Test
+    void testGreeting() {
+        MockEndpoint mockEndpoint = getMockEndpoint("mock:result");
+        mockEndpoint.expectedBodiesReceived("Hello World");
+
+        template.sendBody("direct:start", "World");
+
+        mockEndpoint.assertIsSatisfied();
+    }
+}
+----
+
+=== Using `AdviceWith`
+
+xref:manual::advice-with.adoc[AdviceWith] allows you to modify routes at 
runtime for testing purposes - replacing endpoints, adding interceptors, or 
changing route behavior without modifying production code.
+
+==== Advising existing application routes
+
+The recommended pattern is:
+
+1. Define routes in your *application code* (src/main/java)
+2. Use `AdviceWith` to modify these *existing* routes in your tests
+
+[source,java]
+----
+// Application code: src/main/java/com/example/MyRoutes.java
+public class MyRoutes extends RouteBuilder {
+    @Override
+    public void configure() {
+        from("kafka:input-topic").routeId("my-kafka-route")
+            .to("kafka:output-topic")
+            .to("mock:result");
+    }
+}
+
+// Test code: src/test/java/com/example/MyRoutesTest.java
+@QuarkusTest
+class MyRoutesTest extends CamelQuarkusTestSupport {
+    @BeforeEach
+    public void beforeEach() throws Exception {
+        // Advise the application route
+        AdviceWith.adviceWith(this.context, "my-kafka-route", route -> {
+            
route.weaveByToUri("kafka:output-topic*").replace().to("mock:kafka-stub");
+        });
+    }
+
+    @Test
+    void testRoute() throws Exception {
+        MockEndpoint stub = getMockEndpoint("mock:kafka-stub");
+        stub.expectedMessageCount(1);
+
+        template.sendBody("kafka:input-topic", "test");
+
+        stub.assertIsSatisfied();
+    }
+}
+----
+
+WARNING: Advising routes created via `createRouteBuilder()` in tests can lead 
to unpredictable behavior.
+
+==== Apply advice in `@BeforeEach` or `doBeforeEach`
+
+When all tests in a class need the same advice, apply it in `@BeforeEach` or 
override `doBeforeEach`:
+
+[source,java]
+----
+@QuarkusTest
+class SimpleTest extends CamelQuarkusTestSupport {
+    @BeforeEach
+    public void beforeEach() throws Exception {
+        // Apply advice to EXISTING application route
+        AdviceWith.adviceWith(this.context, "advisedRoute", route -> {
+            route.replaceFromWith("direct:replaced");
+        });
+        // Routes that aren't advised are automatically started after this 
method completes
+    }
+
+    @Test
+    void testAdvisedRoute() throws Exception {
+        MockEndpoint mockEndpoint = getMockEndpoint("mock:result");
+        mockEndpoint.expectedBodiesReceived("Hello World");
+
+        template.sendBody("direct:replaced", "World");
+
+        mockEndpoint.assertIsSatisfied();
+    }
+}
+----
+
+Routes that aren't advised are automatically started after `@BeforeEach` or 
`doBeforeEach` completes. Advice modifications are automatically cleaned up 
between test methods
+
+==== Per-test-method advice using `adviceRoute()`
+
+When you need *different* advice in each test method, use the `adviceRoute()` 
helper method which handles route lifecycle (stop, advice, start) automatically:
+
+[source,java]
+----
+@QuarkusTest
+class PerMethodAdviceTest extends CamelQuarkusTestSupport {
+    @Test
+    void testWithMockOutput() throws Exception {
+        // Apply advice specific to this test on EXISTING application route
+        adviceRoute("my-route", route -> {
+            
route.weaveByToUri("kafka:output*").replace().to("mock:kafka-stub");
+        });
+
+        MockEndpoint stub = getMockEndpoint("mock:kafka-stub");
+        stub.expectedMessageCount(1);
+
+        template.sendBody("kafka:input", "test message");
+
+        stub.assertIsSatisfied();
+    }
+
+    @Test
+    void testWithDifferentAdvice() throws Exception {
+        // Different advice for this test on the same EXISTING route
+        adviceRoute("my-route", route -> {
+            route.weaveByToUri("kafka:output*").replace()
+                .transform(simple("MODIFIED: ${body}"))
+                .to("mock:result");
+        });
+
+        // ... different test assertions
+    }
+}
+----
+
+==== Advice patterns
+
+IMPORTANT: When using `weaveByToUri()`, `weaveByType()`, or similar methods, 
use specific patterns rather than wildcards to avoid unintentionally matching 
endpoints from the main application or other routes.
+
+For example, instead of:
+[source,java]
+----
+// Matches ALL Kafka endpoints in the context
+route.weaveByToUri("kafka:*").replace().to("mock:result");
+----
+
+Use specific endpoint URIs:
+[source,java]
+----
+// Only matches the specific endpoint you intend to advise
+route.weaveByToUri("kafka:my-output-topic*").replace().to("mock:result");
+----
+
+Or use IDs for even more precision:
+[source,java]
+----
+// Uses ID for exact matching
+route.weaveById("kafkaProducer").replace().to("mock:result");
+----
+
+Wildcard patterns like `kafka:*`, `http:*`, or `direct:*` will match **all** 
endpoints of that type throughout the entire `CamelContext`, including routes 
from your main application that the test may not need to modify. This can cause 
unexpected test failures and interference between tests.
+
+==== Advice cleanup between tests
+
+Advice modifications are automatically cleaned up between test methods to 
prevent interference. This ensures that:
+
+* Each test starts with a clean route state
+* Advice from one test doesn't affect subsequent tests
+* Tests remain independent and can run in any order
+
+== Limitations
+
+=== Test lifecycle methods inherited from `CamelTestSupport`
+
+`CamelQuarkusTestSupport` inherits some test lifecycle methods from 
`CamelTestSupport`. However, they should not be used and instead are replaced 
with equivalent methods in `CamelQuarkusTestSupport`.
+
+|===
+|CamelTestSupport lifecycle methods |CamelQuarkusTestSupport equivalent
+
+|`afterAll`
+|`doAfterAll`
+
+|`afterEach`, `afterTestExecution`
+|`doAfterEach`
+
+|`beforeAll`
+|`doAfterConstruct`
+
+|`beforeEach`
+|`doBeforeEach`
+|===
+
+=== Creating a custom Camel registry is not supported
+
+The `CamelQuarkusTestSupport` implementation of `createCamelRegistry` will 
throw `UnsupportedOperationException`.
+
+If you need to bind or unbind objects to the Camel registry, then you can do 
it by one of the following methods.
+
+* Produce named CDI beans
++
+[source,java]
+----
+public class MyBeanProducers {
+    @Produces
+    @Named("myBean")
+    public MyBean createMyBean() {
+        return new MyBean();
+    }
+}
+----
++
+* Override `createCamelContext` (see example above) and invoke 
`camelContext.getRegistry().bind("foo", fooBean)`
+* Use the `@BindToRegistry` annotation
++
+[source,java]
+----
+@QuarkusTest
+class SimpleTest extends CamelQuarkusTestSupport {
+    @BindToRegistry("myBean")
+    MyBean myBean = new MyBean();
+}
+----
++
++
+
+NOTE: Beans bound to the Camel registry from individual test classes, will 
persist for the duration of the test suite execution.
+This could have unintended consequences, depending on your test expectations. 
You can use test profiles to restart the `CamelContext` to avoid this.
diff --git a/docs/modules/ROOT/pages/user-guide/testing/camel-quarkus-test.adoc 
b/docs/modules/ROOT/pages/user-guide/testing/camel-quarkus-test.adoc
new file mode 100644
index 00000000000..5ad74966b0f
--- /dev/null
+++ b/docs/modules/ROOT/pages/user-guide/testing/camel-quarkus-test.adoc
@@ -0,0 +1,209 @@
+= Annotation based testing with `@CamelQuarkusTest`
+
+`@CamelQuarkusTest` configures Camel specific test features with annotation 
attributes, without extending a base class.
+It implies `@QuarkusTest`.
+
+IMPORTANT: `@CamelQuarkusTest` only works in JVM mode.
+
+To use `@CamelQuarkusTest`, add `camel-quarkus-junit` as a test scoped 
dependency to your application.
+
+[source,xml]
+----
+<dependency>
+    <groupId>org.apache.camel.quarkus</groupId>
+    <artifactId>camel-quarkus-junit</artifactId>
+    <scope>test</scope>
+</dependency>
+----
+
+Everything declared on `@CamelQuarkusTest` applies to the whole test class.
+It is set up before the first test method runs and undone after the last one.
+`MockEndpoint` instances are reset after each test method.
+
+== Test routes
+
+Routes for a test class are declared with `routes`.
+They are added before the first test method and removed after the last one.
+Route builder classes declared in a `@CamelQuarkusTest` class, or listed in 
`routes`, are never discovered as application routes.
+
+`CamelContext`, `ProducerTemplate`, `FluentProducerTemplate` and 
`ConsumerTemplate` can be injected with `@Inject`, and endpoints with 
`@EndpointInject`.
+
+[source,java]
+----
+@CamelQuarkusTest(routes = GreetingTest.Routes.class)
+class GreetingTest {
+
+    @Inject
+    ProducerTemplate template;
+
+    @EndpointInject("mock:result")
+    MockEndpoint result;
+
+    @Test
+    void greets() throws Exception {
+        result.expectedBodiesReceived("Hello World");
+        template.sendBody("direct:start", "World");
+        result.assertIsSatisfied();
+    }
+
+    public static class Routes extends RouteBuilder {
+        @Override
+        public void configure() {
+            from("direct:start").transform().simple("Hello 
${body}").to("mock:result");
+        }
+    }
+}
+----
+
+== Advising application routes
+
+Advice for the test class is declared with `advices`, and route consumers are 
replaced with `replaceRouteFromWith`.
+
+[source,java]
+----
+@CamelQuarkusTest(
+        advices = @AdviceRoute(route = "my-kafka-route", advice = 
KafkaRouteTest.StubKafka.class),
+        replaceRouteFromWith = "my-timer-route=direct:trigger")
+class KafkaRouteTest {
+
+    static class StubKafka extends AdviceWithRouteBuilder {
+        @Override
+        public void configure() {
+            
weaveByToUri("kafka:output-topic*").replace().to("mock:kafka-stub");
+        }
+    }
+}
+----
+
+Advice for a single test method is applied with `CamelTestHelper`, which can 
be injected into the test class.
+It is undone after the test method.
+
+[source,java]
+----
+@CamelQuarkusTest
+class MyRouteTest {
+
+    @Inject
+    CamelTestHelper helper;
+
+    @Test
+    void withMock() throws Exception {
+        helper.adviceRoute("my-route", route -> 
route.weaveByToUri("kafka:*").replace().to("mock:kafka"));
+        // ...
+    }
+}
+----
+
+`CamelTestHelper` also provides `getMockEndpoint`, `resetMocks` and 
`startRouteDefinitions`.
+
+== Replacing beans in the Camel registry
+
+Fields and no-arg methods annotated with `@ReplaceInRegistry` are bound to the 
Camel registry, using the member name as the bean name.
+The previous bindings are restored after the last test method.
+The beans are bound before the routes declared with `routes` are added. 
Application routes already exist at that point, as do the routes declared with 
`routes` in <<_shared_mode_and_isolated_mode,isolated mode>>, so routes that 
look up a bean when they are created do not use the replacement.
+Beans provided by CDI cannot be replaced this way. Use 
https://quarkus.io/guides/getting-started-testing#mock-support[`@InjectMock` or 
`QuarkusMock`] for those.
+
+[source,java]
+----
+@CamelQuarkusTest
+class GreeterTest {
+
+    @ReplaceInRegistry
+    Greeter greeter = new FakeGreeter();
+}
+----
+
+== Shared mode and isolated mode
+
+By default, a test class shares the application with the other test classes of 
the module, and its routes are already started when the test class begins.
+Some features need to act before routes are created. They are only available 
when the test class owns its application, which is called isolated mode.
+
+A test class runs in isolated mode when it is annotated with `@TestProfile` 
and no other `@CamelQuarkusTest` class uses the same test profile.
+The usual way is for the test class to be its own test profile, in which case 
it must be public.
+
+[source,java]
+----
+@CamelQuarkusTest(mockEndpointsAndSkip = "kafka:*")
+@TestProfile(OrdersTest.class)
+public class OrdersTest implements QuarkusTestProfile {
+}
+----
+
+Using a feature that is only available in isolated mode fails the test build.
+
+[cols="2,1,1"]
+|===
+| Feature | Shared mode | Isolated mode
+
+| `routes`, `advices`, `replaceRouteFromWith`, `@ReplaceInRegistry`
+| Yes
+| Yes
+
+| `mockEndpoints`, `mockEndpointsAndSkip`, `stubEndpoints`
+| No
+| Yes
+
+| `autoStartupExclude`
+| No
+| Yes
+
+| `@ProvidesBreakpoint`
+| No
+| Yes
+
+| `dumpRouteCoverage`, `dumpRoute`, `shutdownTimeout`
+| Yes
+| Yes
+|===
+
+In isolated mode, `advices` and `replaceRouteFromWith` are applied before 
routes are created.
+
+== Debugging, route coverage and route dumps
+
+A `public static` no-arg method annotated with `@ProvidesBreakpoint` and 
returning `org.apache.camel.spi.Breakpoint` enables the Camel debugger with 
that breakpoint.
+
+`dumpRouteCoverage = true` writes route coverage to 
`target/camel-route-coverage` after each test method. It requires 
`camel-quarkus-management`.
+
+`dumpRoute` writes the routes to `target/camel-route-dump` after each test 
method, in `xml` or `yaml` format.
+It requires `camel-quarkus-xml-io-dsl` for `xml`, and `camel-quarkus-yaml-io` 
for `yaml`.
+
+== Continuous testing
+
+Continuous testing only detects test classes annotated with `@QuarkusTest`, or 
with annotations declared in the test sources that are meta-annotated with 
`@QuarkusTest`.
+To run `@CamelQuarkusTest` classes in continuous testing, annotate them with 
`@QuarkusTest` as well.
+
+[source,java]
+----
+@QuarkusTest
+@CamelQuarkusTest(routes = GreetingTest.Routes.class)
+class GreetingTest {
+}
+----
+
+== Migrating from `CamelQuarkusTestSupport`
+
+[cols="1,1"]
+|===
+| `CamelQuarkusTestSupport` | `@CamelQuarkusTest`
+
+| `createRouteBuilder()`
+| `routes`. The routes apply to the whole test class. Test methods that need 
different routes belong in separate test classes.
+
+| `isMockEndpoints()`, `isMockEndpointsAndSkip()`
+| `mockEndpoints`, `mockEndpointsAndSkip`. These require 
<<_shared_mode_and_isolated_mode,isolated mode>>, including when only the 
routes declared with `routes` are mocked.
+
+| `adviceRoute()`
+| `CamelTestHelper.adviceRoute()` or `advices`
+
+| `getMockEndpoint()`
+| `@EndpointInject` or `CamelTestHelper.getMockEndpoint()`
+
+| `@BindToRegistry`, `bindToRegistry()`
+| `@ReplaceInRegistry` or CDI producers
+
+| `isDumpRouteCoverage()`
+| `dumpRouteCoverage`
+
+| `doBeforeEach()`, `doAfterEach()`, `doAfterConstruct()`, `doAfterAll()`
+| JUnit `@BeforeEach`, `@AfterEach`, `@BeforeAll`, `@AfterAll`
+|===
diff --git a/docs/modules/ROOT/pages/user-guide/testing/external-services.adoc 
b/docs/modules/ROOT/pages/user-guide/testing/external-services.adoc
new file mode 100644
index 00000000000..12aca837917
--- /dev/null
+++ b/docs/modules/ROOT/pages/user-guide/testing/external-services.adoc
@@ -0,0 +1,152 @@
+= Testing with external services
+
+== Testcontainers
+
+Sometimes your application needs to access an external service such as a 
message broker, database, etc.
+If a container image is available for the service of interest, 
https://www.testcontainers.org/[Testcontainers]
+can be used to start and stop these services for testing.
+
+For the application to work properly, it is often essential to pass the 
connection configuration data
+(host, port, user, password, etc. of the remote service) to the application 
before it starts.
+In the Quarkus ecosystem, `QuarkusTestResourceLifecycleManager` serves this 
purpose.
+
+You can start one or more containers in the `start()` method
+and return the connection configuration in the form of a `Map`, where the key 
is the name of a configuration property and the value is the property value.
+The entries of this map are then passed to the application either via command 
line (`-Dkey=value`) in native mode,
+or through a special MicroProfile configuration provider in JVM mode.
+Note that these settings have a higher precedence than the settings in 
`application.properties` file.
+
+[source,java]
+----
+import java.util.Map;
+import java.util.HashMap;
+
+import io.quarkus.test.common.QuarkusTestResourceLifecycleManager;
+import org.testcontainers.containers.GenericContainer;
+import org.testcontainers.containers.wait.strategy.Wait;
+
+public class MyTestResource implements QuarkusTestResourceLifecycleManager {
+
+    private GenericContainer<?> myContainer;
+
+    @Override
+    public Map<String, String> start() {
+        // Start the needed container(s)
+        myContainer = new 
GenericContainer(DockerImageName.parse("my/image:1.0.0"))
+                .withExposedPorts(1234)
+                .waitingFor(Wait.forListeningPort());
+
+        myContainer.start();
+
+        // Pass the configuration to the application under test
+        // You can also pass camel component property names / values to 
automatically configure Camel components
+        return new HashMap<>() {{
+                put("my-container.host", container.getHost());
+                put("my-container.port", "" + container.getMappedPort(1234));
+        }};
+    }
+
+    @Override
+    public void stop() {
+        // Stop the needed container(s)
+        myContainer.stop();
+    }
+}
+----
+
+The defined test resource needs to be referenced from the test classes with 
`@QuarkusTestResource` as shown below:
+
+[source,java]
+----
+import io.quarkus.test.common.QuarkusTestResource;
+import io.quarkus.test.junit.QuarkusTest;
+
+@QuarkusTest
+@QuarkusTestResource(MyTestResource.class)
+class MyTest {
+   ...
+}
+----
+
+More information can be found in the 
https://quarkus.io/guides/getting-started-testing#quarkus-test-resource[Quarkus 
testing guide]. Refer to Camel Quarkus source tree for a 
https://github.com/apache/camel-quarkus/blob/main/integration-tests/google-storage/src/test/java/org/apache/camel/quarkus/component/google/storage/it/GoogleStorageTestResource.java[complete
 example].
+
+== WireMock
+
+It is sometimes useful to stub HTTP interactions with third party services & 
APIs so that tests do not have to connect to live endpoints, as this can incur 
costs and the service may not always be 100% available or reliable.
+
+An excellent tool for mocking & recording HTTP interactions is 
http://wiremock.org/[WireMock]. It is used extensively throughout the Camel 
Quarkus test suite for various component extensions. Here follows a typical 
workflow
+for setting up WireMock.
+
+First set up the WireMock server. Note that it is important to configure the 
Camel component under test to pass any HTTP interactions through the WireMock 
proxy. This is usually achieved by configuring a component property
+that determines the API endpoint URL. Sometimes things are less 
straightforward and some extra work is required to configure the API client 
library, as was the case for 
https://github.com/apache/camel-quarkus/blob/main/integration-tests/twilio/src/main/java/org/apache/camel/quarkus/component/twilio/it/TwilioResource.java#L83[Twilio].
+
+[source,java]
+----
+import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
+import static com.github.tomakehurst.wiremock.client.WireMock.get;
+import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
+import static 
com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import com.github.tomakehurst.wiremock.WireMockServer;
+
+import io.quarkus.test.common.QuarkusTestResourceLifecycleManager;
+
+public class WireMockTestResource implements 
QuarkusTestResourceLifecycleManager {
+
+    private WireMockServer server;
+
+    @Override
+    public Map<String, String> start() {
+        // Setup & start the server
+        server = new WireMockServer(
+            wireMockConfig().dynamicPort()
+        );
+        server.start();
+
+        // Stub an HTTP endpoint. Note that WireMock also supports a record 
and playback mode
+        // https://wiremock.org/docs/record-playback/
+        server.stubFor(
+            get(urlEqualTo("/api/greeting"))
+                .willReturn(aResponse()
+                    .withHeader("Content-Type", "application/json")
+                    .withBody("{\"message\": \"Hello World\"}")));
+
+        // Ensure the camel component API client passes requests through the 
WireMock proxy
+        Map<String, String> conf = new HashMap<>();
+        conf.put("camel.component.foo.server-url", server.baseUrl());
+        return conf;
+    }
+
+    @Override
+    public void stop() {
+        if (server != null) {
+            server.stop();
+        }
+    }
+}
+----
+
+Finally, ensure your test class has the `@QuarkusTestResource` annotation with 
the appropriate test resource class specified as the value. The WireMock server 
will be started before all tests are
+executed and will be shut down when all tests are finished.
+
+[source,java]
+----
+import io.quarkus.test.common.QuarkusTestResource;
+import io.quarkus.test.junit.QuarkusTest;
+
+@QuarkusTest
+@QuarkusTestResource(WireMockTestResource.class)
+class MyTest {
+   ...
+}
+----
+
+More examples of WireMock usage can be found in the Camel Quarkus integration 
test source tree such as in the 
https://github.com/apache/camel-quarkus/blob/main/integration-tests/validator/src/test/java/org/apache/camel/quarkus/component/validator/it/ValidatorTestResource.java[validator
 tests].
+
+== Citrus Testing Framework
+
+The https://citrusframework.org/[Citrus Testing Framework] provides advanced 
integration testing capabilities for Camel Quarkus applications.
+For detailed information about using Citrus with Quarkus test support, see 
xref:manual::integration-test.adoc#_quarkus_test_support[Integration Testing 
with Citrus] in the Apache Camel documentation.

Reply via email to