Skip to content

Commit

Permalink
Merge pull request #996 from picimako/documentation-fixes
Browse files Browse the repository at this point in the history
Various documentation fixes
  • Loading branch information
bbortt authored Sep 25, 2023
2 parents cf23cba + bb34617 commit 93dcb10
Show file tree
Hide file tree
Showing 42 changed files with 164 additions and 167 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public void doExecute(TestContext context) {
final List<RouteDefinition> routesToUse;

if (StringUtils.hasText(routeContext)) {
// now lets parse the routes with JAXB
// now let's parse the routes with JAXB
try {
Object value = CamelUtils.getJaxbContext().createUnmarshaller().unmarshal(new StringSource(context.replaceDynamicContentInString(routeContext)));
if (value instanceof CamelRouteContextFactoryBean) {
Expand Down
2 changes: 1 addition & 1 deletion src/manual/actions-purge-endpoints.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -188,4 +188,4 @@ public SequenceBeforeTest beforeTest() {

Just use this before-test bean in the Spring bean application context and the purge endpoint action is active. Obsolete messages that are waiting on the message endpoints for consumption are purged before the next test in line is executed.

TIP: Purging message endpoints becomes also very interesting when working with server instances in Citrus. Each server component automatically has an inbound message endpoint where incoming messages are stored to internally. Citrus will automatically use this incoming message endpoint as target for the purge action so you can just use the server instance as you know it from your configuration in any purge action.
TIP: Purging message endpoints becomes also very interesting when working with server instances in Citrus. Each server component automatically has an inbound message endpoint where incoming messages are stored too internally. Citrus will automatically use this incoming message endpoint as target for the purge action so you can just use the server instance as you know it from your configuration in any purge action.
2 changes: 1 addition & 1 deletion src/manual/actions-purge-jms.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ NOTE: Citrus provides special support for JMS related features when using the Sp

Notice that we have referenced the *jms* namespace when using the *purge-jms-queues* test action.

Purging the JMS queues in every test case is quite exhausting because every test case needs to define a purging action at the very beginning of the test. Fortunately the test suite definition offers tasks to run before, between and after the test cases which should ease up this tasks a lot. The test suite offers a very simple way to purge the destinations between the tests. See link:#before-suite[testsuite-before-test]for more information about this.
Purging the JMS queues in every test case is quite exhausting because every test case needs to define a purging action at the very beginning of the test. Fortunately the test suite definition offers tasks to run before, between and after the test cases which should ease up these tasks a lot. The test suite offers a very simple way to purge the destinations between the tests. See link:#before-suite[testsuite-before-test] for more information about this.

As you can see in the next example it is quite easy to specify a group of destinations in the Spring configuration that get purged before a test is executed.

Expand Down
6 changes: 3 additions & 3 deletions src/manual/actions-receive.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -492,7 +492,7 @@ actions:
----

In addition to that you can ignore some elements that are skipped in comparison. We will describe this later on in this section.
Now lets continue with message header validation.
Now let's continue with message header validation.

[[receive-message-headers]]
=== Validate message headers
Expand Down Expand Up @@ -903,10 +903,10 @@ In messaging applications the header information often holds message ids, correl
With this information given you can explicitly listen for messages that belong to your test case.
This is very helpful to avoid receiving messages that are still available on the message destination.

Lets say the tested software application keeps sending messages that belong to previous test cases. This could happen in
Let's say the tested software application keeps sending messages that belong to previous test cases. This could happen in
retry situations where the application error handling automatically tries to solve a communication problem that occurred
during previous test cases. As a result a message destination (e.g. a JMS message queue) contains messages that are not
valid any more for the currently running test case. The test case might fail because the received message does not apply
valid anymore for the currently running test case. The test case might fail because the received message does not apply
to the actual use case. So we will definitely run into validation errors as the expected message control values do not match.

Now we have to find a way to avoid these problems. The test could filter the messages on a destination to only receive messages
Expand Down
2 changes: 1 addition & 1 deletion src/manual/actions-send.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ variable by the expression *_${variable-name}_* .
TIP: Use variables wherever you can! At least the important entities of a test should be defined as variables at the beginning.
The test case improves maintainability and flexibility when using variables.

Now lets have a closer look at the sending action. The *'endpoint'* attribute might catch your attention first. This attribute
Now let's have a closer look at the sending action. The *'endpoint'* attribute might catch your attention first. This attribute
references a message endpoint in Citrus configuration by name. As previously mentioned the message endpoint definition lives
in a separate configuration file and contains the actual message transport settings. In this example the *"helloService"* is
referenced which is a message endpoint for sending out messages via JMS or HTTP for instance.
Expand Down
2 changes: 1 addition & 1 deletion src/manual/changes-new.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -540,7 +540,7 @@ Also following _org.springframework.beans.factory.xml.BeanDefinitionParser_ add
|_**SchemaRepositoryParser**_ | `META-INF/citrus/schema-repository/parser`
|===

The bean definition parsers mentioned above are now able to dynamically lookup element parsers that live in other modules. For instance the `SchemaParser` loads and delegates the bean definition parsing to `.xsd` or `.json` related schema parser implementations that live in `citrus-validation-xml` or `citrus-validation-json` modules. The user needs to add these modules to the classpath when using a XML or Json schema in a schema repository.
The bean definition parsers mentioned above are now able to dynamically lookup element parsers that live in other modules. For instance the `SchemaParser` loads and delegates the bean definition parsing to `.xsd` or `.json` related schema parser implementations that live in `citrus-validation-xml` or `citrus-validation-json` modules. The user needs to add these modules to the classpath when using an XML or Json schema in a schema repository.

Also the test action registry is now able to load parser implementation from other modules using the resource lookup mechanism. This way we can delegate to data dictionary parser implementations for `XML` or `Json` when they are present on the classpath.

Expand Down
2 changes: 1 addition & 1 deletion src/manual/data-dictionary.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ For more complex XML payloads where more flexibility is required the XPath data

As expected XPath mapping expressions are more powerful and can better handle complex scenarios with XML namespaces, attributes and node lists. Just like the node mapping dictionary the XPath mapping dictionary also supports variables, functions and an external mapping file.

XPath works fine with namespaces. In general it is good practice to define a namespace context where you map namespace URI values with prefix values. So your XPath expression is more precise and evaluation is strict. In Citrus the *NamespaceContextBuilder* which is also added as a normal Spring bean to the application context manages namespaces used in your XPath expressions. See our XML and XPath chapters in this documentation for detailed description how to accomplish fail safe XPath expressions with namespaces.
XPath works fine with namespaces. In general it is good practice to define a namespace context where you map namespace URI values with prefix values. So your XPath expression is more precise and evaluation is strict. In Citrus the *NamespaceContextBuilder* which is also added as a normal Spring bean to the application context manages namespaces used in your XPath expressions. See our XML and XPath chapters in this documentation for detailed description how to accomplish fail-safe XPath expressions with namespaces.

This completes the XML data dictionary usage in Citrus. Later on we will see some more advanced data dictionary scenarios where we will discuss the usage of dictionary scopes and mapping strategies. But before that let us have a look at other message formats like JSON messages.

Expand Down
2 changes: 1 addition & 1 deletion src/manual/endpoint-adapter.adoc
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[[endpoint-adapter]]
= Endpoint adapter

Endpoint adapter help to customize the behavior of a Citrus server such as HTTP or SOAP web servers. As the servers get started with the Citrus context they are ready to receive incoming client requests. Now there are different ways to process these incoming requests and to provide a proper response message. By default the server will forward the incoming request to a in memory message channel where a test can receive the message and provide a synchronous response. This message channel handling is done automatically behind the scenes so the tester does not care about these things. The tester just uses the server directly as endpoint reference in the test case. This is the default behaviour. In addition to that you can define custom endpoint adapters on the Citrus server in order to change this default behavior.
Endpoint adapter help to customize the behavior of a Citrus server such as HTTP or SOAP web servers. As the servers get started with the Citrus context they are ready to receive incoming client requests. Now there are different ways to process these incoming requests and to provide a proper response message. By default the server will forward the incoming request to an in-memory message channel where a test can receive the message and provide a synchronous response. This message channel handling is done automatically behind the scenes so the tester does not care about these things. The tester just uses the server directly as endpoint reference in the test case. This is the default behaviour. In addition to that you can define custom endpoint adapters on the Citrus server in order to change this default behavior.

You set the custom endpoint adapter directly on the server configuration as follows:

Expand Down
16 changes: 8 additions & 8 deletions src/manual/endpoint-arquillian.adoc
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
[[arquillian]]
= Arquillian support

Arquillian is a well known integration test framework that comes with a great feature set when it comes to Java EE testing inside of a full qualified application server. With Arquiliian you can deploy your Java EE services in a real application server of your choice and execute the tests inside the application server boundaries. This makes it very easy to test your Java EE services in scope with proper JNDI resource allocation and other resources provided by the application server. Citrus is able to connect with the Arquillian test case. Speaking in more detail your Arquillian test is able to use a Citrus extension in order to use the Citrus feature set inside the Arquillian boundaries.
Arquillian is a well known integration test framework that comes with a great feature set when it comes to Java EE testing inside a full qualified application server. With Arquillian you can deploy your Java EE services in a real application server of your choice and execute the tests inside the application server boundaries. This makes it very easy to test your Java EE services in scope with proper JNDI resource allocation and other resources provided by the application server. Citrus is able to connect with the Arquillian test case. Speaking in more detail your Arquillian test is able to use a Citrus extension in order to use the Citrus feature set inside the Arquillian boundaries.

Read the next section in order to find out more about the Citrus Arquillian extension.

[[citrus-arquillian-extension]]
== Citrus Arquillian extension

Arquillian offers a fine mechanism for extensions adding features to the Arquillian test setup and test execution. The Citrus extension respectively adds Citrus framework instance creation and Citrus test execution to the Arquillian world. First of all lets have a look at the extension descriptor properties settable via *arquillian.xml* :
Arquillian offers a fine mechanism for extensions adding features to the Arquillian test setup and test execution. The Citrus extension respectively adds Citrus framework instance creation and Citrus test execution to the Arquillian world. First of all let's have a look at the extension descriptor properties settable via *arquillian.xml* :

[source,xml]
----
Expand Down Expand Up @@ -42,12 +42,12 @@ Now that we have added the extension descriptor with all properties we need to a
</dependency>
----

Now everything is set up to use Citrus within Arquillian. Lets use Citrus functionality in a Arquillian test case.
Now everything is set up to use Citrus within Arquillian. Let's use Citrus functionality in an Arquillian test case.

[[client-side-testing]]
== Client side testing

Arquillian separates client and container side testing. When using client side testing the test case is executed outside of the application container deployment. This means that your test case has no direct access to container managed resources such as JNDI resources. On the plus side it is not necessary to include your test in the container deployment. The test case interacts with the container deployment as a normal client would do. Lets have a look at a first example:
Arquillian separates client and container side testing. When using client side testing the test case is executed outside the application container deployment. This means that your test case has no direct access to container managed resources such as JNDI resources. On the plus side it is not necessary to include your test in the container deployment. The test case interacts with the container deployment as a normal client would do. Let's have a look at a first example:

[source,java]
----
Expand Down Expand Up @@ -116,12 +116,12 @@ The Citrus test designer provides Java DSL methods for building the test logic.

When the Citrus test case is executed the messages are sent over the wire. The respective response message is received with well known Citrus receive message logic. We can validate the response messages accordingly and make sure the client call was done right. In case something goes wrong within Citrus test execution the framework will raise exceptions accordingly. As a result the JUnit test method is successful or failed with errors coming from Citrus test execution.

This is how Citrus and Arquillian can interact in a test scenario where the test deployment is managed by Arquillian and the client side actions take place within Citrus. This is a great way to combine both frameworks with Citrus being able to call different service API endpoints in addition with validating the outcome. This was a client side test case where the test logic was executed outside of the application container. Arquillian also supports container remote test cases where we have direct access to container managed resources. The following section describes how this works with Citrus.
This is how Citrus and Arquillian can interact in a test scenario where the test deployment is managed by Arquillian and the client side actions take place within Citrus. This is a great way to combine both frameworks with Citrus being able to call different service API endpoints in addition with validating the outcome. This was a client side test case where the test logic was executed outside the application container. Arquillian also supports container remote test cases where we have direct access to container managed resources. The following section describes how this works with Citrus.

[[container-side-testing]]
== Container side testing

In previous sections we have seen how to combine Citrus with Arquillian in a client side test case. This is the way to go for all test cases that do not need to have access on container managed resources. Lets have a look at a sample where we want to gain access to a JMS queue and connection managed by the application container.
In previous sections we have seen how to combine Citrus with Arquillian in a client side test case. This is the way to go for all test cases that do not need to have access on container managed resources. Let's have a look at a sample where we want to gain access to a JMS queue and connection managed by the application container.

[source,java]
----
Expand Down Expand Up @@ -190,7 +190,7 @@ This is how to combine Citrus and Arquillian in order to build integration tests
[[test-runners]]
== Test runners

In the previous sections we have used the Citrus *TestDesigner* in order to construct a Citrus test case to execute within the Arquillian boundaries. The nature of the test designer is to aggregate all Java DSL method calls in order to build a complete Citrus test case before execution is done via the Citrus framework. This approach can cause some unexpected behavior when mixing the Citrus Java DSL method calls with Arquillian test logic. Lets describe this by having a look at an example where th mixture of test designer and pure Java test logic causes unseen problems.
In the previous sections we have used the Citrus *TestDesigner* in order to construct a Citrus test case to execute within the Arquillian boundaries. The nature of the test designer is to aggregate all Java DSL method calls in order to build a complete Citrus test case before execution is done via the Citrus framework. This approach can cause some unexpected behavior when mixing the Citrus Java DSL method calls with Arquillian test logic. Let's describe this by having a look at an example where th mixture of test designer and pure Java test logic causes unseen problems.

[source,java]
----
Expand Down Expand Up @@ -272,7 +272,7 @@ public void testDesignRuntimeMixture(@CitrusResource TestRunner runner) throws E
}
----

The test logic has not changed significantly. We use the Citrus *TestRunner* as method injected parameter instead of the *TestDesigner* . And this is pretty much the trick. Now the Java DSL methods do execute the Citrus test logic immediately. This is why the syntax of the Citrus Java DSL methods have changed a little bit. We now use a anonymous interface implementation for constructing the send/receive test action logic. As a result we can use the Citrus Java DSL as normal code and we can mix the runtime Java logic as each statement is executed immediately.
The test logic has not changed significantly. We use the Citrus *TestRunner* as method injected parameter instead of the *TestDesigner* . And this is pretty much the trick. Now the Java DSL methods do execute the Citrus test logic immediately. This is why the syntax of the Citrus Java DSL methods have changed a little bit. We now use an anonymous interface implementation for constructing the send/receive test action logic. As a result we can use the Citrus Java DSL as normal code and we can mix the runtime Java logic as each statement is executed immediately.

With Java lambda expressions our code looks even more straight forward and less verbose as we can skip the anonymous interface implementations. With Java 8 you can write the same test like this:

Expand Down
2 changes: 1 addition & 1 deletion src/manual/endpoint-camel.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,7 @@ public CamelContext camelContext() {
----

The route has an exception handling block defined that is called as soon as the exchange processing ends up in some error or exception.
With Citrus you can also simulate a exchange exception when sending back a synchronous response to a calling route.
With Citrus you can also simulate an exchange exception when sending back a synchronous response to a calling route.

.Java
[source,java,indent=0,role="primary"]
Expand Down
Loading

0 comments on commit 93dcb10

Please sign in to comment.