Introduction
This article is about automating functional testing of SOAP based web services. Any application which has multiple exposed web services needs to be tested along with different inputs and the corresponding responses should be validated to make sure that the business logic used by the web services is working. This functionality can be modeled in licensed tools like SOAP UI Pro with little hardship and the approach mentioned here needs very minimal configuration changes (compared to SOAP UI) for every new added web service.
The idea mentioned below can be implemented easily by using Core Java with reflections and can be integrated as part of the build to test the web services like JUnit.
The required steps to implement this are:
- Compile the WSDL’s using JAXB equals plugin
- Maintain the requests, responses.
- Compare the responses (baseline and actual)
Compile WSDL’s
The JAXB classes generated without JAXB equals plugin does not have equals method implemented. Once, WSDL’s are compiled using the JAXB equals plugin then JAXB classes which are generated will have equals method which helps in comparing the baseline and actual response XML’s.
Plugin jars can be downloaded from the link
http://confluence.highsource.org/display/J2B/JAXB2+Basics+Plugins.
The script mentioned below is “ant script” which is used to compile using JAXB equals plugin
<path id="jaxb2-commons.classpath">
<fileset dir="%JAXB_DIST_DIR%">
<include name="**/*.jar" />
</fileset>
</path>
<wsimport wsdl="@{dir-wsdl}/@{name-wsdl}"
taskname="wsimport-@{service}"
destdir="@{dest-dir}"
sourcedestdir="@{source-dest-dir}"
package="@{package}"
keep="@{keep}"
verbose="@{verbose}"
xdebug="@{xdebug}"
xnocompile="@{xnocompile}"
target="2.1">
<binding dir="@{dir-wsdl}" includes="bindings-wsdl-@{name-wsdl}.xml,
bindings-schema-@{name-wsdl}.xml" />
<xjcArg value="-Xequals" />
<!-- Generates per-package jaxb.index file which lists all of the
schema-derived classes in this package.-->
<span style="line-height: 1.5;"> <xjcArg value="-Xjaxbindex" /></span>
<xjcArg value="-Xsetters" />
</wsimport>
Maintain requests & responses
Below is the sample directory structure to maintain XML test case requests and responses. WSDLs can be maintained as a part of WSDL directory. Baseline requests and response can be captured from any tool like Eclipse web services explorer or SOAP UI etc.
It is better to maintain a naming convention, so that the baseline response xml name can be derived from the request xml name.
Load and compare baseline & actual responses
In the web service client, the code mentioned below can be added to compare the baseline and actual responses so as to determine whether the test case has passed or not
1. JAXContext instance JAX needs to be created
Context jaxbContext = JAXBContext.newInstance(ObjectFactory.class);
//2. Use JAXBContext instance to create the Unmarshaller.
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
//3. Use the Unmarshaller to unmarshal the XML document to get an instance of JAXBElement.
JAXBElement unmarshalledObject = (JAXBElement)unmarshaller.unmarshal
ClassLoader.getSystemResourceAsStream("addDoubles/responses/actuals
/add2Resp.xml"));
//4. Get the instance of the required JAXB Root Class from the JAXBElement.
AddResp addRespObj1 = unmarshalledObject.getValue();
unmarshalledObject =(JAXBElement)unmarshaller.unmarshal(
ClassLoader.getSystemResourceAsStream("addDoubles/responses/actuals
/add2Resp.xml"));
//5. Compare the testcase baseline and actual response.
AddResp addRespObj2 = unmarshalledObject.getValue();
If(addRespObj2.equals(addRespObj1)){ System.out.println
(“Test case is passed”); }
Make it Generic
The details which are mentioned above explain about automating testing of single web service operation. In order to make it generic and be able to add any number of new web service operations without coding web service clients and automate their testing, java reflection and load configuration information for each web service has to be used. The configuration information is
- Service class for the corresponding web service
- Operation to Invoke
- The input jaxb class
- The output jaxb class
The above configuration information can be stored in a config file in the %operationname% (add in this case) directory inside XML directory of the proposed structure.
Code to invoke the Add Service below
// load addservice class using ServiceClass parameter in config //
using java reflection
Below is simplified version
AddService addSrv = new AddService(%URL_FROM_CONFIG%);
Add add = addSrv.getPort();
By using all the above information, a Core Java framework can be written which is used to dynamically load the config information and test the web services by loading the service classes and invoke the methods using java reflection.
If you would like to find out more about how APIs could help you make the most out of your current infrastructure while enabling you to open your digital horizons, do give us a call at +44 (0)203 475 7980 or email us at Salesforce@coforge.com
Other useful links:
SOA Service Registry/Repository and Service Discovery
Telecom - Service Integration
Message Oriented Middleware