Add Unit Testing examples
diff --git a/README.adoc b/README.adoc
index d169916..cb49d8a 100644
--- a/README.adoc
+++ b/README.adoc
@@ -27,7 +27,7 @@
 == Examples
 
 // examples: START
-Number of Examples: 46 (0 deprecated)
+Number of Examples: 47 (0 deprecated)
 
 [width="100%",cols="4,2,4",options="header"]
 |===
@@ -53,6 +53,8 @@
 
 | link:camel-example-spring-boot-type-converter/README.adoc[Spring Boot Type Converter] (camel-example-spring-boot-type-converter) | Beginner | An example showing how to create custom type converter with Camel and Spring Boot
 
+| link:camel-example-spring-boot-unit-testing/README.adoc[Spring Boot Unit Testing] (camel-example-spring-boot-unit-testing) | Beginner | An example showing how to write unit tests with Camel and Spring Boot
+
 | link:camel-example-spring-boot-xml/readme.adoc[Spring Boot XML] (camel-example-spring-boot-xml) | Beginner | An example showing how to work with Camel routes in XML files and Spring Boot
 
 | link:camel-example-spring-boot-aws2-s3/README.adoc[Spring Boot Aws2 S3] (camel-example-spring-boot-aws2-s3) | Cloud | An example showing the Camel AWS2 S3 component with Spring Boot
diff --git a/camel-example-spring-boot-unit-testing/README.adoc b/camel-example-spring-boot-unit-testing/README.adoc
new file mode 100644
index 0000000..4f7bdc6
--- /dev/null
+++ b/camel-example-spring-boot-unit-testing/README.adoc
@@ -0,0 +1,22 @@
+== Camel Example Spring Boot
+
+This example different ways to unit test Camel routes in Spring Boot using Mock component and adviceWith techniques.
+
+=== How to run
+
+You can run this example using
+
+    mvn test
+
+=== Help and contributions
+
+If you hit any problem using Camel or have some feedback, then please
+https://camel.apache.org/support.html[let us know].
+
+We also love contributors, so
+https://camel.apache.org/contributing.html[get involved] :-)
+
+The Camel riders!
+
+
+
diff --git a/camel-example-spring-boot-unit-testing/pom.xml b/camel-example-spring-boot-unit-testing/pom.xml
new file mode 100644
index 0000000..d0c1222
--- /dev/null
+++ b/camel-example-spring-boot-unit-testing/pom.xml
@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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>
+		<artifactId>examples</artifactId>
+		<groupId>org.apache.camel.springboot.example</groupId>
+		<version>3.7.0-SNAPSHOT</version>
+	</parent>
+	<modelVersion>4.0.0</modelVersion>
+
+	<artifactId>camel-example-spring-boot-unit-testing</artifactId>
+	<name>Camel SB Examples :: Unit testing with Camel</name>
+	<description>An example showing how to write unit tests with Camel and Spring Boot</description>
+
+	<properties>
+		<category>Beginner</category>
+
+		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+		<spring.boot-version>${spring-boot-version}</spring.boot-version>
+	</properties>
+
+	<dependencyManagement>
+		<dependencies>
+			<!-- Spring Boot BOM -->
+			<dependency>
+				<groupId>org.springframework.boot</groupId>
+				<artifactId>spring-boot-dependencies</artifactId>
+				<version>${spring.boot-version}</version>
+				<type>pom</type>
+				<scope>import</scope>
+			</dependency>
+			<!-- Camel BOM -->
+			<dependency>
+				<groupId>org.apache.camel.springboot</groupId>
+				<artifactId>camel-spring-boot-bom</artifactId>
+				<version>${camel-version}</version>
+				<type>pom</type>
+				<scope>import</scope>
+			</dependency>
+		</dependencies>
+	</dependencyManagement>
+
+	<dependencies>
+
+		<!-- Spring Boot -->
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter</artifactId>
+		</dependency>
+		<!-- Camel -->
+		<dependency>
+			<groupId>org.apache.camel.springboot</groupId>
+			<artifactId>camel-spring-boot-starter</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.camel.springboot</groupId>
+			<artifactId>camel-stream-starter</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.camel.springboot</groupId>
+			<artifactId>camel-jms-starter</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.camel.springboot</groupId>
+			<artifactId>camel-activemq-starter</artifactId>
+		</dependency>
+
+		<!-- test -->
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-test</artifactId>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.camel</groupId>
+			<artifactId>camel-test-spring-junit5</artifactId>
+			<scope>test</scope>
+		</dependency>
+	</dependencies>
+
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.springframework.boot</groupId>
+				<artifactId>spring-boot-maven-plugin</artifactId>
+				<version>${spring-boot-version}</version>
+				<executions>
+					<execution>
+						<goals>
+							<goal>repackage</goal>
+						</goals>
+					</execution>
+				</executions>
+			</plugin>
+			<!-- Camel Maven Package Plugin to generate Type Converter Loader source code - Camel 3.x way -->
+			<plugin>
+				<groupId>org.codehaus.mojo</groupId>
+				<artifactId>build-helper-maven-plugin</artifactId>
+				<executions>
+					<execution>
+						<phase>initialize</phase>
+						<goals>
+							<goal>add-source</goal>
+							<goal>add-resource</goal>
+						</goals>
+						<configuration>
+							<sources>
+								<source>src/generated/java</source>
+							</sources>
+							<resources>
+								<resource>
+									<directory>src/generated/resources</directory>
+								</resource>
+							</resources>
+						</configuration>
+					</execution>
+				</executions>
+			</plugin>
+			<!-- Adds mgenerated Type Converter Loader source in src/generated to the source path - Camel 3.x way -->
+			<plugin>
+				<groupId>org.apache.camel</groupId>
+				<artifactId>camel-package-maven-plugin</artifactId>
+				<version>${camel-version}</version>
+				<executions>
+					<execution>
+						<id>generate</id>
+						<goals>
+							<goal>generate-component</goal>
+						</goals>
+						<phase>process-classes</phase>
+					</execution>
+				</executions>
+			</plugin>
+		</plugins>
+	</build>
+</project>
\ No newline at end of file
diff --git a/camel-example-spring-boot-unit-testing/src/main/java/org/apache/camel/example/spring/boot/Application.java b/camel-example-spring-boot-unit-testing/src/main/java/org/apache/camel/example/spring/boot/Application.java
new file mode 100644
index 0000000..7a00387
--- /dev/null
+++ b/camel-example-spring-boot-unit-testing/src/main/java/org/apache/camel/example/spring/boot/Application.java
@@ -0,0 +1,30 @@
+/*
+ *
+ *  * Licensed to the Apache Software Foundation (ASF) under one or more
+ *  * contributor license agreements.  See the NOTICE file distributed with
+ *  * this work for additional information regarding copyright ownership.
+ *  * The ASF licenses this file to You under the Apache License, Version 2.0
+ *  * (the "License"); you may not use this file except in compliance with
+ *  * the License.  You may obtain a copy of the License at
+ *  *
+ *  *      http://www.apache.org/licenses/LICENSE-2.0
+ *  *
+ *  * Unless required by applicable law or agreed to in writing, software
+ *  * distributed under the License is distributed on an "AS IS" BASIS,
+ *  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  * See the License for the specific language governing permissions and
+ *  * limitations under the License.
+ *
+ */
+package org.apache.camel.example.spring.boot;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Application {
+
+	public static void main(String[] args) {
+		SpringApplication.run(Application.class);
+	}
+}
diff --git a/camel-example-spring-boot-unit-testing/src/main/java/org/apache/camel/example/spring/boot/InterceptorSimulatedErrorException.java b/camel-example-spring-boot-unit-testing/src/main/java/org/apache/camel/example/spring/boot/InterceptorSimulatedErrorException.java
new file mode 100644
index 0000000..eb8d38a
--- /dev/null
+++ b/camel-example-spring-boot-unit-testing/src/main/java/org/apache/camel/example/spring/boot/InterceptorSimulatedErrorException.java
@@ -0,0 +1,29 @@
+/*
+ *
+ *  * Licensed to the Apache Software Foundation (ASF) under one or more
+ *  * contributor license agreements.  See the NOTICE file distributed with
+ *  * this work for additional information regarding copyright ownership.
+ *  * The ASF licenses this file to You under the Apache License, Version 2.0
+ *  * (the "License"); you may not use this file except in compliance with
+ *  * the License.  You may obtain a copy of the License at
+ *  *
+ *  *      http://www.apache.org/licenses/LICENSE-2.0
+ *  *
+ *  * Unless required by applicable law or agreed to in writing, software
+ *  * distributed under the License is distributed on an "AS IS" BASIS,
+ *  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  * See the License for the specific language governing permissions and
+ *  * limitations under the License.
+ *
+ */
+package org.apache.camel.example.spring.boot;
+
+public class InterceptorSimulatedErrorException extends RuntimeException{
+
+	public InterceptorSimulatedErrorException() {
+	}
+
+	public InterceptorSimulatedErrorException(String message) {
+		super(message);
+	}
+}
diff --git a/camel-example-spring-boot-unit-testing/src/main/java/org/apache/camel/example/spring/boot/MockSimulatedErrorException.java b/camel-example-spring-boot-unit-testing/src/main/java/org/apache/camel/example/spring/boot/MockSimulatedErrorException.java
new file mode 100644
index 0000000..4f5863f
--- /dev/null
+++ b/camel-example-spring-boot-unit-testing/src/main/java/org/apache/camel/example/spring/boot/MockSimulatedErrorException.java
@@ -0,0 +1,30 @@
+/*
+ *
+ *  * Licensed to the Apache Software Foundation (ASF) under one or more
+ *  * contributor license agreements.  See the NOTICE file distributed with
+ *  * this work for additional information regarding copyright ownership.
+ *  * The ASF licenses this file to You under the Apache License, Version 2.0
+ *  * (the "License"); you may not use this file except in compliance with
+ *  * the License.  You may obtain a copy of the License at
+ *  *
+ *  *      http://www.apache.org/licenses/LICENSE-2.0
+ *  *
+ *  * Unless required by applicable law or agreed to in writing, software
+ *  * distributed under the License is distributed on an "AS IS" BASIS,
+ *  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  * See the License for the specific language governing permissions and
+ *  * limitations under the License.
+ *
+ */
+
+package org.apache.camel.example.spring.boot;
+
+public class MockSimulatedErrorException extends RuntimeException{
+
+	public MockSimulatedErrorException() {
+	}
+
+	public MockSimulatedErrorException(String message) {
+		super(message);
+	}
+}
diff --git a/camel-example-spring-boot-unit-testing/src/main/java/org/apache/camel/example/spring/boot/UnitTestsRouter.java b/camel-example-spring-boot-unit-testing/src/main/java/org/apache/camel/example/spring/boot/UnitTestsRouter.java
new file mode 100644
index 0000000..b264332
--- /dev/null
+++ b/camel-example-spring-boot-unit-testing/src/main/java/org/apache/camel/example/spring/boot/UnitTestsRouter.java
@@ -0,0 +1,125 @@
+/*
+ *
+ *  * 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.example.spring.boot;
+
+import java.util.ArrayList;
+
+import org.apache.camel.builder.RouteBuilder;
+
+import org.springframework.stereotype.Component;
+
+import static org.apache.camel.builder.AggregationStrategies.flexible;
+
+@Component
+public class UnitTestsRouter extends RouteBuilder {
+	@Override
+	public void configure() throws Exception {
+
+		// @formatter:off
+
+		// Example 5 : Simulating error from mocked endpoint
+		onException(MockSimulatedErrorException.class)
+				.handled(true)
+				.to("mock:g");
+
+		// Example 6 : Simulating error from mocked endpoint
+		onException(InterceptorSimulatedErrorException.class)
+				.handled(true)
+				.to("mock:j");
+
+		// Example 1 : Simple mock testing
+		from("direct:simple-mock")
+				.to("mock:a");
+
+		// Example 2 : Mock testing with expects expression
+		from("direct:mock-expects-expression")
+				.to("mock:b");
+
+		// Example 3 : Mock testing with descending counter expression
+		from("direct:mock-expects-descending")
+				.to("mock:c");
+
+		// Example 3 : Mock testing with ascending counter expression
+		from("direct:mock-expects-ascending")
+				.to("mock:d");
+
+		// Example 4 : Providing canned response from mocked endpoint
+		from("direct:mock-response")
+				.to("mock:e");
+
+		// Example 5 : Simulating error from mocked endpoint
+		from("direct:mock-simulate-error")
+				.to("mock:f");
+
+		// Example 6 : Simulating error with interceptor
+		from("direct:interceptor-simulate-error").routeId("example6")
+				.to("mock:h");
+
+		// Example 7 : Advising and mocking endpoints
+		from("direct:advice-mock-endpoints").routeId("example7")
+				.choice()
+					.when(simple("${body} contains 'K'"))
+						.to("seda:k")
+					.otherwise()
+						.to("seda:l");
+
+		// Example 8 : Advising and mocking endpoints
+		from("jms:abc").routeId("example8")
+				.choice()
+					.when(simple("${body} contains 'M'"))
+				.to("seda:m")
+					.otherwise()
+				.to("seda:n");
+
+		// Example 9 : Weaving processor by ID
+		from("direct:advice-weave-by-id-replace").routeId("example9")
+				.transform(simple("${body.toLowerCase()}")).id("node9");
+
+		// Example 10 : Weaving producer by ID and replacing node
+		from("direct:advice-producer-by-id-replace").routeId("example10")
+				.split(body(), flexible().accumulateInCollection(ArrayList.class))
+					.transform(simple("${body.toLowerCase()}"))
+					.to("seda:p")
+				.end()
+				.to("mock:q");
+
+		// Example 11 : Weaving producer by ID and removing node
+		from("direct:advice-weave-by-id-remove").routeId("example11")
+				.transform(simple("${body.toLowerCase()}")).id("node11");
+
+		// Example 12 : Weaving node by type
+		from("direct:advice-weave-by-type").routeId("example12")
+				.split(body(), flexible().accumulateInCollection(ArrayList.class))
+					.transform(simple("${body.toLowerCase()}"))
+					.to("mock:t")
+				.end()
+				.to("mock:u");
+
+		// Example 13 : Selecting specific node using select* method
+		from("direct:advice-weave-by-type-and-select").routeId("example13")
+				.split(body(), flexible().accumulateInCollection(ArrayList.class))
+					.transform(simple("${body.toUpperCase()}"))
+					.to("mock:v")
+				.end()
+				.to("mock:w");
+		// @formatter:on
+
+	}
+
+}
diff --git a/camel-example-spring-boot-unit-testing/src/main/resources/application.properties b/camel-example-spring-boot-unit-testing/src/main/resources/application.properties
new file mode 100644
index 0000000..4ec0ff7
--- /dev/null
+++ b/camel-example-spring-boot-unit-testing/src/main/resources/application.properties
@@ -0,0 +1,10 @@
+# the name of Camel
+camel.springboot.name = CamelUnitTestsExample
+
+# to configure logging levels
+logging.level.org.springframework = INFO
+logging.level.org.apache.camel.spring.boot = INFO
+logging.level.org.apache.camel.impl = INFO
+logging.level.org.apache.camel = INFO
+logging.level.sample.camel = INFO
+#logging.level.sample.camel = DEBUG
diff --git a/camel-example-spring-boot-unit-testing/src/test/java/CamelSpringBootUnitTests.java b/camel-example-spring-boot-unit-testing/src/test/java/CamelSpringBootUnitTests.java
new file mode 100644
index 0000000..dcad167
--- /dev/null
+++ b/camel-example-spring-boot-unit-testing/src/test/java/CamelSpringBootUnitTests.java
@@ -0,0 +1,425 @@
+/*
+ *
+ *  * 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.
+ *
+ */
+import java.util.List;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.AdviceWith;
+import org.apache.camel.builder.AdviceWithRouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.example.spring.boot.Application;
+import org.apache.camel.example.spring.boot.InterceptorSimulatedErrorException;
+import org.apache.camel.example.spring.boot.MockSimulatedErrorException;
+import org.apache.camel.model.SplitDefinition;
+import org.apache.camel.model.ToDefinition;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+import org.junit.jupiter.api.Test;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import static org.apache.camel.builder.Builder.body;
+import static org.apache.camel.builder.Builder.simple;
+import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.fail;
+
+@CamelSpringBootTest
+@SpringBootTest(classes = Application.class)
+public class CamelSpringBootUnitTests {
+
+	@Autowired
+	private CamelContext camelContext;
+
+	@Autowired
+	private ProducerTemplate producerTemplate;
+
+	// @formatter:off
+	@Test
+	public void testSimpleMock() throws InterruptedException {
+		// Getting mock endpoint object from the context
+		MockEndpoint mockA = camelContext.getEndpoint("mock:a", MockEndpoint.class);
+
+		// setting expectation for a message body received by mock using one the expect* methods
+		mockA.expectedBodiesReceived("Hello world");
+		// setting expectation for a message body received by mock using one the expect* methods
+		mockA.message(0).header("Counter").isEqualTo(1);
+
+		// sending data to route consumer
+		producerTemplate.sendBodyAndHeader("direct:simple-mock", "Hello world", "Counter", 1);
+
+		// asserting expectations are satisfied
+		mockA.assertIsSatisfied();
+	}
+
+	@Test
+	public void testMockWithCustomExpect() throws Exception {
+		// Getting mock endpoint object from the context
+		MockEndpoint mockB = camelContext.getEndpoint("mock:b", MockEndpoint.class);
+
+		// setting expectation for a number of messages that will arrive at mock
+		mockB.expectedMessageCount(3);
+
+		// expects method allow providing custom logic to verify expectations
+		mockB.expects(() -> mockB.getExchanges().stream()
+				.reduce(0, (previous, exchange) -> {
+					int current = exchange.getIn().getHeader("Counter", Integer.class);
+					if (current <= previous){
+						// We fail explicitly if counter current counter is less than previous
+						fail ("Counter is not greater than previous counter");
+					} else if (current - previous != 1){
+						// We fail explicitly if gap more than 1 detected between previous and current counter
+						fail("Gap detected: previous: " + previous + " current: " + current);
+					}
+					return current;
+					// Combiner
+				}, (prev, current) -> current));
+
+		// Change to non consequent counter number to see test fail
+		// Sending test data to route consumer
+		producerTemplate.sendBodyAndHeader("direct:mock-expects-expression", "A", "Counter", 1);
+		producerTemplate.sendBodyAndHeader("direct:mock-expects-expression", "A", "Counter", 2);
+		producerTemplate.sendBodyAndHeader("direct:mock-expects-expression", "A", "Counter", 3);
+
+		// Asserting expectations are satisfied
+		mockB.assertIsSatisfied();
+	}
+
+	@Test
+	public void testMockExpectDescending() throws Exception {
+		// Getting mock endpoint object from the context
+		MockEndpoint mockC = camelContext.getEndpoint("mock:c", MockEndpoint.class);
+
+		// setting expectation for a number of messages that will arrive at mock
+		mockC.expectedMessageCount(3);
+
+		// setting expectation for a attribute, in this case defined in header to be in a descending order
+		mockC.expectsDescending().header("Counter");
+		// setting expectation for a message body
+		mockC.allMessages().body().isEqualTo("A");
+
+		// Change to non consequent counter number to see test fail
+		// Sending test data to route consumer
+		// TODO 7 : Does not work exactly descending 1, 2, 1
+		producerTemplate.sendBodyAndHeader("direct:mock-expects-descending", "A", "Counter", 3);
+		producerTemplate.sendBodyAndHeader("direct:mock-expects-descending", "A", "Counter", 2);
+		producerTemplate.sendBodyAndHeader("direct:mock-expects-descending", "A", "Counter", 1);
+
+		// Asserting expectations are satisfied
+		mockC.assertIsSatisfied();
+	}
+
+	@Test
+	public void testMockExpectAscending() throws Exception {
+		// Getting mock endpoint object from the context
+		MockEndpoint mockD = camelContext.getEndpoint("mock:d", MockEndpoint.class);
+
+		// setting expectation for a number of messages that will arrive at mock
+		mockD.expectedMessageCount(3);
+
+		// setting expectation for a attribute, in this case defined in header to be in a ascending order
+		mockD.expectsAscending().header("Counter");
+		// setting expectation for a message body to contain no duplicates
+		mockD.expectsNoDuplicates().body();
+
+		// Change to non consequent counter number to see test fail
+		// Sending test data to route consumer
+		producerTemplate.sendBodyAndHeader("direct:mock-expects-ascending", "A", "Counter", 1);
+		producerTemplate.sendBodyAndHeader("direct:mock-expects-ascending", "B", "Counter", 2);
+		producerTemplate.sendBodyAndHeader("direct:mock-expects-ascending", "C", "Counter", 3);
+
+		// asserting expectations are satisfied
+		mockD.assertIsSatisfied();
+	}
+
+	@Test
+	public void testMockComponent() throws Exception {
+		// Getting mock endpoint object from the context
+		MockEndpoint mockE = camelContext.getEndpoint("mock:e", MockEndpoint.class);
+
+		// setting expectation for a number of messages that will arrive at mock
+		mockE.expectedMessageCount(2);
+		// setting expectation for the contents of messages that will arrive at mock
+		mockE.expectedBodiesReceived("1", "2");
+
+		// defining behavior of a mock by providing a canned stubbed response to any exchanges arrived
+		mockE.whenAnyExchangeReceived(e -> e.getIn().setBody("B"));
+		// defining behavior of a mock by providing a canned stubbed response for a particular exchange by index
+		mockE.whenExchangeReceived(2, e -> e.getIn().setBody("C"));
+
+		// Change to non consequent counter number to see test fail
+		// Sending test data to route consumer and obtaining response messages for further validation
+		final String mockResponse1 = producerTemplate.requestBody("direct:mock-response", "1", String.class);
+		final String mockResponse2 = producerTemplate.requestBody("direct:mock-response", "2", String.class);
+
+		// Asserting expectations are satisfied
+		mockE.assertIsSatisfied();
+		// Asserting expectations towards message body contents are satisfied
+		assertEquals("B", mockResponse1);
+		assertEquals("C", mockResponse2);
+	}
+
+	@Test
+	public void testMockSimulateError() throws Exception {
+		// Getting mock endpoint object from the context
+		MockEndpoint mockF = camelContext.getEndpoint("mock:f", MockEndpoint.class);
+		MockEndpoint mockG = camelContext.getEndpoint("mock:g", MockEndpoint.class);
+
+		// defining behavior of a mock by providing a canned stubbed response (exception) to any exchanges arrived
+		mockF.whenAnyExchangeReceived(e -> e.setException(new MockSimulatedErrorException("Simulated error")));
+
+		// setting expectation for the contents of messages that will arrive at mock
+		mockG.expectedBodiesReceived("A");
+
+		// Sending test data to route consumer
+		producerTemplate.sendBody("direct:mock-simulate-error", "A");
+
+		// Asserting expectations are satisfied
+		mockF.assertIsSatisfied();
+		mockG.assertIsSatisfied();
+	}
+
+	@Test
+	public void testMockSimulateErrorWithInterceptor() throws Exception {
+		// Getting mock endpoint object from the context
+		MockEndpoint mockH = camelContext.getEndpoint("mock:h", MockEndpoint.class);
+		MockEndpoint mockJ = camelContext.getEndpoint("mock:j", MockEndpoint.class);
+
+		// Advising endpoint in AOP style by providing routeId
+		AdviceWith.adviceWith(camelContext, "example6",
+						// intercepting an exchange on route to the endpoint
+				a -> a.interceptSendToEndpoint("mock:h")
+						// skipping sending exchange to the original endpoint
+						.skipSendToOriginalEndpoint()
+						// Throwing an error to simulate failure
+						.process(exchange -> {
+							throw new InterceptorSimulatedErrorException("Error");
+						}));
+
+		// setting expectation for the absence of messages that will arrive at mock
+		mockH.expectedMessageCount(0);
+		// setting expectation for the contents of messages that will arrive at mock
+		mockJ.expectedBodiesReceived("A");
+
+		// Sending test data to route consumer
+		producerTemplate.sendBody("direct:interceptor-simulate-error", "A");
+
+		// Asserting expectations are satisfied
+		mockH.assertIsSatisfied();
+		mockJ.assertIsSatisfied();
+	}
+
+	@Test
+	public void testAdvisingRouteAndMockingEndpoints() throws Exception {
+		// Advising endpoint in AOP style by providing routeId
+		AdviceWith.adviceWith(camelContext, "example7",
+				// mocking all endpoint in advised route
+				AdviceWithRouteBuilder::mockEndpoints);
+
+		// Getting mock endpoint object from the context
+		MockEndpoint mockK = camelContext.getEndpoint("mock:seda:k", MockEndpoint.class);
+		MockEndpoint mockL = camelContext.getEndpoint("mock:seda:l", MockEndpoint.class);
+
+		// setting expectation for the contents of messages that will arrive at mock
+		mockK.expectedBodiesReceived("K");
+		mockL.expectedBodiesReceived("L");
+
+		// Sending test data to route consumer
+		producerTemplate.sendBody("direct:advice-mock-endpoints", "K");
+		producerTemplate.sendBody("direct:advice-mock-endpoints", "L");
+
+		// Asserting expectations are satisfied
+		mockK.assertIsSatisfied();
+		mockL.assertIsSatisfied();
+	}
+
+
+	@Test
+	public void testAdvisedRouteAndWeaveConsumerFromWith() throws Exception {
+		// Getting mock endpoint object from the context
+		MockEndpoint mockM = camelContext.getEndpoint("mock:seda:m", MockEndpoint.class);
+		MockEndpoint mockN = camelContext.getEndpoint("mock:seda:n", MockEndpoint.class);
+
+		// Advising endpoint in AOP style by providing routeId
+		AdviceWith.adviceWith(camelContext, "example8",
+				a -> {
+						// Replacing a consumer (from) with a another consumer
+						a.replaceFromWith("direct:advice-replace-consumer");
+						// Mocking particular endpoint by providing a pattern match
+						a.mockEndpoints("seda:*");
+				});
+
+		// setting expectation for the contents of messages that will arrive at mock
+		mockM.expectedBodiesReceived("M");
+		mockN.expectedBodiesReceived("N");
+
+		// Sending test data to route consumer
+		producerTemplate.sendBody("direct:advice-replace-consumer", "M");
+		producerTemplate.sendBody("direct:advice-replace-consumer", "N");
+
+		// Asserting expectations are satisfied
+		mockM.assertIsSatisfied();
+		mockN.assertIsSatisfied();
+	}
+
+	@Test
+	public void testAdvisingRouteAndWeaveByIdAndReplacingNode() throws Exception {
+		// Advising endpoint in AOP style by providing routeId
+		AdviceWith.adviceWith(camelContext, "example9",
+				a -> { 		// weaving particular node in the route by id
+					a.weaveById("node9")
+							// providing advised (weaved) node replacement
+							.replace().transform(simple("${body.toUpperCase()}"));
+					// adding new (mock) node to the route definition
+					a.weaveAddLast().to("mock:o"); });
+
+		// Getting mock endpoint object from the context
+		MockEndpoint mockO = camelContext.getEndpoint("mock:o", MockEndpoint.class);
+
+
+
+		// setting expectation for the contents of messages that will arrive at mock
+		mockO.expectedBodiesReceived("HELLO WORLD");
+
+		// Sending test data to route consumer
+		producerTemplate.sendBody("direct:advice-weave-by-id-replace", "Hello World");
+
+		// Asserting expectations are satisfied
+		mockO.assertIsSatisfied();
+	}
+
+
+	@Test
+	public void testAdvisingRouteAndProducerWeaveByToUriAndReplaceNode() throws Exception {
+		// Getting mock endpoint object from the context
+		MockEndpoint mockP = camelContext.getEndpoint("mock:p", MockEndpoint.class);
+		MockEndpoint mockQ = camelContext.getEndpoint("mock:q", MockEndpoint.class);
+
+		// Advising endpoint in AOP style by providing routeId
+		AdviceWith.adviceWith(camelContext, "example10",
+				a -> { 		// weaving particular node in the route by URI
+					 	 	a.weaveByToUri("seda:p")
+							// providing advised (weaved) node replacement
+							.replace().to("mock:p"); });
+
+		// setting expectation for the contents of messages that will arrive at mock
+		mockP.expectedBodiesReceived("a", "b", "c");
+		mockQ.message(0).body().isInstanceOf(List.class);
+
+		// Sending test data to route consumer
+		producerTemplate.sendBody("direct:advice-producer-by-id-replace", "a,b,c");
+
+		// Asserting expectations are satisfied
+		mockQ.assertIsSatisfied();
+		mockP.assertIsSatisfied();
+	}
+
+	@Test
+	public void testAdvisingRouteAndWeaveByIdAndRemoveNode() throws Exception {
+		// Advising endpoint in AOP style by providing routeId
+		AdviceWith.adviceWith(camelContext, "example11",
+				a -> { 	// adding a node at the end of the route definition
+					a.weaveAddLast().to("mock:r");
+					// weaving particular node in the route by URI
+					a.weaveById("node11")
+							// and removing advised node
+							.remove();
+				});
+
+		// Getting mock endpoint object from the context
+		MockEndpoint mockR = camelContext.getEndpoint("mock:r", MockEndpoint.class);
+
+		// setting expectation for the contents of messages that will arrive at mock
+		mockR.expectedBodiesReceived("Hello World");
+
+		// Sending test data to route consumer
+		producerTemplate.sendBody("direct:advice-weave-by-id-remove", "Hello World");
+
+		// Asserting expectations are satisfied
+		mockR.assertIsSatisfied();
+	}
+
+	@Test
+	public void testAdvisingRouteAndWeaveByIdAndAddNode() throws Exception {
+		// Advising endpoint in AOP style by providing routeId
+		AdviceWith.adviceWith(camelContext, "example12",
+						// find the splitter node
+				a -> a.weaveByType(SplitDefinition.class)
+						// and insert the route snippet before it
+						.before()
+							// definition of the newly added node
+							.filter(body().contains("c"))
+							.transform(simple("${body} advised")));
+
+		// Getting mock endpoint object from the context
+		MockEndpoint mockT = camelContext.getEndpoint("mock:t", MockEndpoint.class);
+		MockEndpoint mockU = camelContext.getEndpoint("mock:u", MockEndpoint.class);
+
+		// setting expectation for the contents of messages that will arrive at mock
+		mockT.expectedBodiesReceived("a", "b", "c advised");
+		mockU.message(0).body().isInstanceOf(List.class);
+
+		// Sending test data to route consumer
+		producerTemplate.sendBody("direct:advice-weave-by-type", "a,b,c");
+
+		// Asserting expectations are satisfied
+		mockT.assertIsSatisfied();
+		mockU.assertIsSatisfied();
+
+		// Resetting mock endpoints and removing weaved new node
+		MockEndpoint.resetMocks(camelContext);
+
+		// Sending test data to route consumer - this time without
+		producerTemplate.sendBody("direct:advice-weave-by-type", "a,b,c");
+		mockT.expectedBodiesReceived("a", "b", "c");
+		mockU.message(0).body().isInstanceOf(List.class);
+
+		// Asserting expectations are satisfied
+		mockT.assertIsSatisfied();
+		mockU.assertIsSatisfied();
+	}
+
+	@Test
+	public void testAdvisingRouteAndWeaveByTypeAndReplacingNodeWithSelect() throws Exception {
+		// Advising endpoint in AOP style by providing routeId
+		AdviceWith.adviceWith(camelContext, "example13",
+				// find by type the 'to' (consumer)
+				a -> a.weaveByType(ToDefinition.class)
+						// select first matching type using on of select* methods
+						.selectFirst()
+						// and replace it with the another consumer
+						.replace().to("mock:x"));
+
+		// Getting mock endpoint object from the context
+		MockEndpoint mockV = camelContext.getEndpoint("mock:v", MockEndpoint.class);
+		MockEndpoint mockX = camelContext.getEndpoint("mock:x", MockEndpoint.class);
+
+		// we expect zero messages for 'mock:v' as it is weaved and replaced by 'mock:x'
+		mockV.expectedMessageCount(0);
+		// 'mock:x' will receive all messages destined to 'mock:v'
+		mockX.expectedBodiesReceived("A", "B", "C");
+
+		// Sending test data to route consumer - this time without
+		producerTemplate.sendBody("direct:advice-weave-by-type-and-select", "a,b,c");
+
+		// Asserting expectations are satisfied
+		mockV.assertIsSatisfied();
+		mockX.assertIsSatisfied();
+	}
+	// @formatter:on
+}
diff --git a/pom.xml b/pom.xml
index 67328a4..d34b302 100644
--- a/pom.xml
+++ b/pom.xml
@@ -80,7 +80,8 @@
         <module>camel-example-spring-cloud-servicecall</module>
         <module>camel-example-spring-cloud-serviceregistry</module>
         <module>camel-example-spring-boot-widget-gadget</module>
-    </modules>
+		<module>camel-example-spring-boot-unit-testing</module>
+	</modules>
 
     <properties>
         <!-- for symbolicName in OSGi examples we only want the artifactId, eg camel-example-sql -->