Welcome!

Java Authors: Ezhil Arasan Babaraj, Maureen O'Gara, Bruce Armstrong, Liz McMillan, Walter H. Pinson, III

Related Topics: SOA & WOA, XML

SOA & WOA: Article

ESB Testing Strategies with Mule

Will it break anything?

Level Two: Functional Testing - Message Transformation, Validation, and Routing
Though similar to the previous tests in the sense that they are based on JUnit, the following tests are not truly unit tests and come closer to functional ones (routing testing, for example, implies firing an instance of Mule ESB). It is important to ensure that the transformation scripts (XSL or other techniques) you use produce the expected results for known inputs. This can be easily achieved by defining a set of typical acceptable messages, applying the desired transformation (or chain of transformations) to them, and comparing the outcome with what was expected. For this, you will find that XMLUnit is of great help. Similarly, if you plan to validate either incoming or outgoing messages, it is worth checking that the schemas or DTDs you embed are relevant to the messages you will have to deal with. This is a no-brainer and can be achieved with a technique similar to the one mentioned just before. More interesting, content-based routing (CBR) configuration, whether it is payload- or properties-based, must also be properly tested. You certainly want to build confidence that the different tests you have written are correct and handle normal and exceptional situations blissfully. This can be achieved by leveraging Mule ESB's modular configuration, as shown in Figure 1.

As you can see, the CBR configuration bits have been pulled out from the monolithic configuration into a specific fragment using in-memory channels as sources and destinations for messages to route. At test time, the production configuration, which typically contains endpoints that connect to remote services, is replaced by a simple one that provides the bare minimum required to run the routing logic. You might wonder what the point of redefining the in-memory end points is and why not have them in the CBR configuration.

The reason I do this is because I use specific connectors in production for them and a generic one for test. If this is not the case for you, then these endpoints could very well be moved to the routing configuration. Another important aspect of the test configuration is that it specifies a synchronous behavior for the sake of allowing the tests to be run in a single thread. Here again, the Mule functional tests library allows you to bootstrap Mule, load the configuration files, register test components to listen to the targeted endpoints, and check that all the messages were correctly routed, all this in a way that is JUnit-compliant. Listing 1 shows an excerpt of a parent abstract I used to test a message properties-based router.

Notice how MuleClient is leveraged both to register a test component easily and send a test message to the target CBR inbound endpoint.

Level Three: Integration Testing - End-to-End Tests
This last level of testing implies deploying the whole configuration in a testing environment that is as close to the production one as possible and exercising the ESB with different happy and failing messaging scenarios. This round of testing will help to validate the configuration as a whole, including components configuration. connection properties, and transactional settings. There are several difficulties to overcome in this process. Here are the three main ones and some possible mitigation techniques:

Sending realistic but innocuous messages to external systems. This can be addressed by following the test message pattern from Gregor Hohpe's Enterprise Integration Patterns: systems can be designed to recognize a particular property as a flag for test messages and only do first-line validation on them before dropping them.

Injecting test messages into a variety of inbound endpoints. ESBs support an incredible variety of protocols - this is one of their key strengths. This also complicates thorough testing because you don't necessarily want your test framework to speak a zillion languages and to be able to have write access on all the resources' inbound endpoints just for the sake of creating test messages. To solve this conundrum, I leverage Mule's capacity to support several endpoints for a particular inbound router to unify all the test message injections on the SOAP protocol. Here is a configuration sample from Mule's examples that shows an inbound router with heterogeneous inbound end-point transports, including SOAP:

<mule-descriptor name="EchoUMO"
implementation="org.mule.components.simple.EchoComponent">
<inbound-router>
<endpoint address="axis:http://localhost:65081/services"
transformers="HttpRequestToSoapRequest" />
<endpoint address="axis:http://localhost:65082/services"/>
<endpoint address="vm://echo" />
</inbound-router>
</mule-descriptor>

By adding a SOAP endpoint alongside the one(s) you already have, you gain the capacity to inject messages at the same level, hence to hit the same component and the outbound routers that follow it. Of course, this does not test the endpoint or the particular transformation(s) that can be associated with it, but this is acceptable because we can trust both to have been already thoroughly tested (by the particular endpoint transport writer or by transformation validation as explained before). Moreover, the actual endpoint initialization configuration will be tested, which is already pretty good. Why unify on SOAP? Because it opens the possibility of leveraging testing tools like soapUI and their capacity to run test suites on remote Web services.

Keeping track of the delivery of messages to external systems. Interrogating all the systems that have been contacted with test messages after the suite has run to ensure they all received what was expected would be too tedious to realize. How to keep track of these test messages? One option could be to run Mule ESB with its logging level set to DEBUG and analyze the message paths by tracking them with their correlation IDs. This is very possible. I decided to follow a simpler and coarser approach, which would give me enough certitude about what happened to the different messages I have sent. For this, I decided to leverage component routing statistics to ensure that the expected number of messages where routed to the expected endpoints (including error messages to error processing components). Of course, if two messages get cross-sent to wrong destinations, the count will not notice that. But this error would be caught anyway because each destination will complain about the error, hence raising the count of error messages processed. I achieved this by exposing statistics over SOAP with a simple component that has two main methods: reset statistics and get statistics for a list of components as shown in Listing 2.

The fact that this is accessible via SOAP makes it possible to call this component in the same soapUI test suite used to exercise the different endpoints. As you might guess, the statistics get reset before sending any test message (acting as a fixture setup that establishes a known initial state) and get analyzed after all the test messages have been sent. Figure 2 is an example of a small test suite after it has run. The addictive green color we see here tells us that all messages were accepted by the ESB and that we have confidence they all ended where they were supposed to.

Closing Note
Of course, all this testing would be worthless without the backing of a proper SCM and build management system. Thanks to Maven and the modularization of Mule ESB into many different artifacts, it is possible to strictly control what you are including in the ESB instance you will run.

Similarly, it's a good idea to have all configuration-related files built and deployed as a versioned artifact, whether it's a JAR added to the ESB instance classpath or a ZIP that you explode somewhere for Mule to read. This will make you confident about what you test and what you deploy: after "certifying" version x.y.z of your ESB configuration, you will have it rolled out to production in a well-defined and packaged manner. The three levels of testing strategies detailed above should give you some ideas about how to gain confidence in your ESB configuration. Not everything there will be relevant to your particular needs but I believe they will give you some interesting food for thought.

Resources

More Stories By David Dossot

David Dossot has worked as a software engineer and architect for more than 14 years. He is a co-author of Mule in Action and is the project despot of the JCR Transport and a member of the Mule Community Committee. He is the project lead of NxBRE, an open source business rules engine for the .NET platform (selected for O'Reilly's Windows Developer Power Tools). He is also a judge for the Jolt Product Excellence Awards and has written several articles for SD Magazine. He holds a Production Systems Engineering Diploma from ESSTIN.

Comments (0)

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.