As in all software projects, quality assurance with thorough testing in integration projects is a key factor to success. Test-driven development focuses exactly on this aspect: unit and integration testing of integration elements must be done as soon as possible. The tests used in these phases must also be reproducible so that they can be run automatically in case of changes in the integration logic, thus guaranteeing that no unintended changes are made.
Oracle SOA/BPM Suite is a powerful tool suite for integration. This article shows how test-driven development can be done with the Oracle tooling. Integration elements built with Oracle SOA/BPM Suite are SCA composites made up of several components. Since mainly the integration layer is concerned, there is quite often heavy usage of external web services, database adapters, etc. The composites also usually have an inbound interface the invocation of which is the starting point of the integration logic.
As it can be seen from above, the key to testing SCA composites is to define an inbound message and assert the data found in various other messages during the integration logic. Some easy scenarios can instantly be identified. XSLT transformations within the composites can be unit-tested without the complete logic itself for example. Likewise, end2end testing is also easily done – at least for a web service interface – thus assuring at least that the result is what we expected. The problem is that for end2end testing, the correct functionality of back-end systems is a prerequisite. If the back-end functionality is developed parallel to the integration logic, end2end testing is far away from test-driven development.
There is, however, a possibility offered by the tooling itself: the composite test framework. With the help of this framework incoming messages can be defined and for each wire (a connection between two components or – more importantly for our purpose – a connection between a component and an external service/adapter) assertions and emulates can be specified. That means if a service is not yet available, its responses can be emulated within Oracle SOA/BPM Suite. Furthermore, outbound service requests and responses for services already available can be checked for correctness with the help of assertions. Multiple test scenarios can be defined and deployed with the composite itself. After deployment, the defined test cases can be started and the test results examined. There are also Ant scripts available so that a nightly test of all integration elements can theoretically be integrated into an appropriate continuous integration run. More information on the composite test framework can be found here for example.
This framework is, however, not completely adequate for real test-driven development. As stated before, assertions and emulates are defined on the wires – meaning that the wires (which are defined as part of the integration logic development) are required first before tests can be created. In case of reorganization of the integration logic, wires are often dropped and recreated. Dropping a wire means that all assertions and emulates in all tests are dropped too. Complex XML structures can be externalized so that they are still available in this case but the assertions and emulates need to be defined again after the wire is recreated. Another difficulty are the static emulates and assertions required by the tooling. In case of loops for example where a component calls an external service multiple times, defining an emulation of the service means that the services always return the same response which is not always satisfactory.
Although the composite test framework itself is not extensible, a lot of functionality is available through the help of the public APIs. With the help of these APIs and some Java knowledge an own test framework not having these limitations can be constructed. The goal is to have a single framework supporting all test aspects of the integration layer. Unit testing of XSLT artifacts can be easily integrated into this Java framework. Following functionality is an excerpt of what is possible by using the SOA Suite APIs:
- Rerouting external references to a mock service implemented in the same framework (in Java) including changing references to standard web services so that database or file adapters can also be mocked for example
- Human task handling (finishing the human task with a predefined outcome and predefined values)
- BPMN queries (traversal of BPMN nodes, checking of payload at given nodes)
The APIs are offering a lot more, so that the custom framework can easily support multiple test aspects required by the projects. Additionally, by extending the framework with the usage of the OSB APIs, integration elements implemented with OSB can also be tested in the same way. We are using the possibility of a custom test framework in almost all of our integration projects. To see the custom framework in action, take a look at our session held at the JAX conference (in German language).
Test creation can be truly done parallel to the integration logic development with the help of this custom framework. Only some SCA data (composite name and revision) and component data (service reference name for mocking, human task component name for human task mocking) is required to bind the assertion or emulation (mock services) defined in Java code to the correct location in the composite. Since everything is implemented in Java, dynamic mocks are not a problem at all. The possibilities that can be found in JUnit can also be easily applied to the test cases. A reorganization of the integration logic is not a problem because the test cases only reference logical names – these do not change often and even in case of a change during the refactoring, the tests can be easily modified to use the correct logical names. Since we are using standard JUnit tests, an integration into a continuous integration environment is also common practice.
We have seen that although the built-in testing possibilities of the SOA/BPM Suite are not completely adequate for a truly test-driven approach, the rich APIs provided by the tool suite makes the creation of a custom test framework possible. This custom framework is capable of supporting the thorough testing requirements of integration elements.