You are on page 1of 10

SoapUI is a useful tool for testing web services.

Not only makes it possible to


test deployed web services, but it also offers the possibility to mock any "exte
rnal" service needed by the service you want to test. As a result, you can test
your web service independently from any other external service.
The following basic example describes how to test a service that computes the pr
ice of a trip (TripPriceService). It invokes one service that returns prices for
hotel rooms (HotelPriceService) and one service that returns prices for flights
(FlightPriceService).
Formula : price = duration * rooms * getRoomPrice() + adults * getFlightPrice(fr
om, to)
Here are the WSDLs of the three services.
TripPriceService.wsdl
<?xml version='1.0' encoding='UTF-8'?><wsdl:definitions name="TripPriceServiceFa
cadeService"
targetNamespace="http://trip.price.service" xmlns:ns1="http://cxf.apache.org/b
indings/xformat"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://trip.pric
e.service" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<wsdl:types>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="unqualifie
d"
targetNamespace="http://trip.price.service" xmlns:tns="http://trip.price.s
ervice" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="getTripPrice" type="tns:getTripPrice" />
<xs:element name="getTripPriceResponse" type="tns:getTripPriceResponse" />
<xs:complexType name="getTripPrice">
<xs:sequence>
<xs:element minOccurs="0" name="trip" type="tns:trip" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="trip">
<xs:sequence>
<xs:element name="adults" type="xs:int" />
<xs:element name="duration" type="xs:int" />
<xs:element minOccurs="0" name="from" type="xs:string" />
<xs:element name="rooms" type="xs:int" />
<xs:element minOccurs="0" name="to" type="xs:string" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="getTripPriceResponse">
<xs:sequence>
<xs:element name="return" type="xs:float" />
</xs:sequence>
</xs:complexType>
<xs:element name="TripPriceServiceException" type="tns:TripPriceServiceExc
eption" />
<xs:complexType name="TripPriceServiceException">
<xs:sequence />
</xs:complexType>
</xs:schema>
</wsdl:types>
<wsdl:message name="TripPriceServiceException">
<wsdl:part element="tns:TripPriceServiceException" name="TripPriceServiceExc
eption">
</wsdl:part>
</wsdl:message>
<wsdl:message name="getTripPrice">
<wsdl:part element="tns:getTripPrice" name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:message name="getTripPriceResponse">
<wsdl:part element="tns:getTripPriceResponse" name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:portType name="ITripPriceServiceFacade">
<wsdl:operation name="getTripPrice">
<wsdl:input message="tns:getTripPrice" name="getTripPrice">
</wsdl:input>
<wsdl:output message="tns:getTripPriceResponse" name="getTripPriceResponse
">
</wsdl:output>
<wsdl:fault message="tns:TripPriceServiceException" name="TripPriceService
Exception">
</wsdl:fault>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="TripPriceServiceFacadeServiceSoapBinding" type="tns:ITripP
riceServiceFacade">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/ht
tp" />
<wsdl:operation name="getTripPrice">
<soap:operation soapAction="" style="document" />
<wsdl:input name="getTripPrice">
<soap:body use="literal" />
</wsdl:input>
<wsdl:output name="getTripPriceResponse">
<soap:body use="literal" />
</wsdl:output>
<wsdl:fault name="TripPriceServiceException">
<soap:fault name="TripPriceServiceException" use="literal" />
</wsdl:fault>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="TripPriceServiceFacadeService">
<wsdl:port binding="tns:TripPriceServiceFacadeServiceSoapBinding" name="Trip
PriceServiceFacadePort">
<soap:address location="http://localhost:8080/trip-price-0.0.1-SNAPSHOT/we
bservices/TripPriceService" />
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
HotelPriceService.wsdl
<?xml version='1.0' encoding='UTF-8'?><wsdl:definitions name="HotelPriceServiceF
acadeService"
targetNamespace="http://external.services/hotel" xmlns:ns1="http://cxf.apache.
org/bindings/xformat"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://external.
services/hotel"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/200
1/XMLSchema">
<wsdl:types>
<xs:schema elementFormDefault="unqualified" targetNamespace="http://external
.services/hotel"
version="1.0" xmlns:tns="http://external.services/hotel" xmlns:xs="http://
www.w3.org/2001/XMLSchema">
<xs:element name="getRoomPrice" type="tns:getRoomPrice" />
<xs:element name="getRoomPriceResponse" type="tns:getRoomPriceResponse" />
<xs:complexType name="getRoomPrice">
<xs:sequence />
</xs:complexType>
<xs:complexType name="getRoomPriceResponse">
<xs:sequence>
<xs:element name="return" type="xs:float" />
</xs:sequence>
</xs:complexType>
</xs:schema>
</wsdl:types>
<wsdl:message name="getRoomPrice">
<wsdl:part element="tns:getRoomPrice" name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:message name="getRoomPriceResponse">
<wsdl:part element="tns:getRoomPriceResponse" name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:portType name="IHotelPriceServiceFacade">
<wsdl:operation name="getRoomPrice">
<wsdl:input message="tns:getRoomPrice" name="getRoomPrice">
</wsdl:input>
<wsdl:output message="tns:getRoomPriceResponse" name="getRoomPriceResponse
">
</wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="HotelPriceServiceFacadeServiceSoapBinding" type="tns:IHote
lPriceServiceFacade">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/ht
tp" />
<wsdl:operation name="getRoomPrice">
<soap:operation soapAction="" style="document" />
<wsdl:input name="getRoomPrice">
<soap:body use="literal" />
</wsdl:input>
<wsdl:output name="getRoomPriceResponse">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="HotelPriceServiceFacadeService">
<wsdl:port binding="tns:HotelPriceServiceFacadeServiceSoapBinding" name="Hot
elPriceServiceFacadePort">
<soap:address location="http://localhost:8088/external-services-0.0.1-SNAP
SHOT/webservices/HotelPriceService" />
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
FlightPriceService.wsdl
<?xml version='1.0' encoding='UTF-8'?>
<wsdl:definitions name="FlightPriceServiceFacadeService" targetNamespace="http:/
/external.services/flight"
xmlns:ns1="http://cxf.apache.org/bindings/xformat" xmlns:soap="http://schemas.
xmlsoap.org/wsdl/soap/"
xmlns:tns="http://external.services/flight" xmlns:wsdl="http://schemas.xmlsoap
.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<wsdl:types>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="unqualifie
d"
targetNamespace="http://external.services/flight" xmlns:tns="http://extern
al.services/flight"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="getFlightPrice" type="tns:getFlightPrice" />
<xs:element name="getFlightPriceResponse" type="tns:getFlightPriceResponse
" />
<xs:complexType name="getFlightPrice">
<xs:sequence>
<xs:element minOccurs="0" name="from" type="xs:string" />
<xs:element minOccurs="0" name="to" type="xs:string" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="getFlightPriceResponse">
<xs:sequence>
<xs:element name="return" type="xs:float" />
</xs:sequence>
</xs:complexType>
<xs:element name="LocationNotFoundException" type="tns:LocationNotFoundExc
eption" />
<xs:complexType name="LocationNotFoundException">
<xs:sequence />
</xs:complexType>
</xs:schema>
</wsdl:types>
<wsdl:message name="LocationNotFoundException">
<wsdl:part element="tns:LocationNotFoundException" name="LocationNotFoundExc
eption">
</wsdl:part>
</wsdl:message>
<wsdl:message name="getFlightPrice">
<wsdl:part element="tns:getFlightPrice" name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:message name="getFlightPriceResponse">
<wsdl:part element="tns:getFlightPriceResponse" name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:portType name="IFlightPriceServiceFacade">
<wsdl:operation name="getFlightPrice">
<wsdl:input message="tns:getFlightPrice" name="getFlightPrice">
</wsdl:input>
<wsdl:output message="tns:getFlightPriceResponse" name="getFlightPriceResp
onse">
</wsdl:output>
<wsdl:fault message="tns:LocationNotFoundException" name="LocationNotFound
Exception">
</wsdl:fault>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="FlightPriceServiceFacadeServiceSoapBinding" type="tns:IFli
ghtPriceServiceFacade">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/ht
tp" />
<wsdl:operation name="getFlightPrice">
<soap:operation soapAction="" style="document" />
<wsdl:input name="getFlightPrice">
<soap:body use="literal" />
</wsdl:input>
<wsdl:output name="getFlightPriceResponse">
<soap:body use="literal" />
</wsdl:output>
<wsdl:fault name="LocationNotFoundException">
<soap:fault name="LocationNotFoundException" use="literal" />
</wsdl:fault>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="FlightPriceServiceFacadeService">
<wsdl:port binding="tns:FlightPriceServiceFacadeServiceSoapBinding" name="Fl
ightPriceServiceFacadePort">
<soap:address location="http://localhost:8088/external-services-0.0.1-SNAP
SHOT/webservices/FlightPriceService" />
</wsdl:port>
</wsdl:service>
</wsdl:definitions>

For the next steps we assume the web service we want to test is deployed and the
external services are not.

1. How to create a soapUI project


In the menu select "File" -> "New soapUI Project"
Set the project name, for example "trip-price-service"
Set the initial WSDL, for example "http://localhost:8080/trip-price-0.0.1-SNAPSH
OT/webservices/TripPriceService?wsdl"
Click "OK"
As a result, you get the "trip-price-service" project containing the "TripPriceS
erviceFacadeServiceSoapBinding" interface.

2. How to generate a test suite


Right click on the "TripPriceServiceFacadeServiceSoapBinding" interface and sele
ct "Generate TestSuite"
Click "OK"
Enter a name for your test suite, for example "TripPriceServiceFacadeServiceSoap
Binding TestSuite"
Click "OK"
As a result you get the "TripPriceServiceFacadeServiceSoapBinding TestSuite" tes
t suite, that includes the "getTripPrice TestCase" test case. The test case alre
ady contains the generated "getTripPrice" test request.

3. How to configure the test case


Setting a timeout for the test case is a good habit, so your test does not run f
orever, in case something goes wrong.
Double click the test case
Click the "Set options for the test case" button (with a monkey wrench and a scr
ewdriver)
Set a timeout in milliseconds, for example "5000"
Click "OK"

4. How to configure the test request


Double-click the "getTripPrice" test request
Edit the request to ask for the price of the following trip : from Berlin to Par
is, for 2 adults, lasting 3 days, one room needed
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmln
s:trip="http://trip.price.service">
<soapenv:Header/>
<soapenv:Body>
<trip:getTripPrice>
<trip>
<adults>2</adults>
<duration>3</duration>
<from>Berlin</from>
<rooms>1</rooms>
<to>Paris</to>
</trip>
</trip:getTripPrice>
</soapenv:Body>
</soapenv:Envelope>
Click the "Submit request to specified endpoint URL" button (green triangle)
As a result, we get a SOAP fault, because the external services we need are not
available. We will mock all of them.
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<soap:Fault>
<faultcode>soap:Server</faultcode>
<faultstring>Could not send Message.</faultstring>
</soap:Fault>
</soap:Body>
</soap:Envelope>

5. How to mock external services


5.1 How to import the WSDL of the external service
Right click on the projet and select "Add WSDL"
Set the WSDL location, for example "/home/ubuntu/workspace/test-webservice-soapu
i/trip-price/trip-price-service/src/main/resources/wsdl/HotelPriceService.wsdl"
Click "OK"
As a result, it adds a new interface to the project : "HotelPriceServiceFacadeSe
rviceSoapBinding".
5.2 How to add a mock response to the test case
Double click the test case to open the test case editor.
Right click and select "Append Step" -> "Mock Response"
Specify a name for the new step, for example "getRoomPrice Mock Response" and cl
ick "OK"
Select the "getRoomPrice" operation of the "HotelPriceServiceFacadeServiceSoapBi
nding" interface.
Set the port, here "8088"
Set the path, here "/external-services-0.0.1-SNAPSHOT/webservices/HotelPriceServ
ice"
Click "OK"
Edit the generated response, to return a price, for example "55.0"
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmln
s:hot="http://external.services/hotel">
<soapenv:Header/>
<soapenv:Body>
<hot:getRoomPriceResponse>
<return>55.0</return>
</hot:getRoomPriceResponse>
</soapenv:Body>
</soapenv:Envelope>
Set the start step of the mock response in the "MockResponse Properties" tab to
"getTripPrice". So the mock service will start listening to requests as soon as
the getTripPrice request is send.
5.3 How to add assertions on the getRoomPrice request
Here we can check the request schema and the parameter values
We launch the test case, to trigger a request to the mock service, it will make
assertion configuration easier.
Click the "Runs this testcase" button (green triangle) in the test case editor
You should see a request in the mock response editor.
Click the "Assertions" tab
Click the "Adds an assertion to this item" button
Select "Schema Compliance" and click "OK"
Check the definition url to validate by and click "OK"
The assertion should appear as valid.
5.4 Now we do the same for FlightPriceService.
Right click on the projet and select "Add WSDL"
Set the WSDL location, for example "/home/ubuntu/workspace/test-webservice-soapu
i/trip-price/trip-price-service/src/main/resources/wsdl/FlightPriceService.wsdl"
Click "OK"
As a result, it adds a new interface to the project : "FlightPriceServiceFacadeS
erviceSoapBinding".
Double click the test case to open the test case editor.
Right click and select "Append Step" -> "Mock Response"
Specify a name for the new step, for example "getFlightPrice Mock Response" and
click "OK"
Select the "getFlightPrice" operation of the "FlightPriceServiceFacadeServiceSoa
pBinding" interface.
Set the port, here "8088"
Set the path, here "/external-services-0.0.1-SNAPSHOT/webservices/FlightPriceSer
vice"
Click "OK"
Edit the generated response, to return a price, for example "49.99"
Set the start step of the mock response in the "MockResponse Properties" tab to
"getTripPrice". So the mock service will start listening to requests as soon as
the getTripPrice request is send.
Click the "Runs this testcase" button (green triangle) in the test case editor
You should see a request in the mock response editor.
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:getFlightPrice xmlns:ns2="http://external.services/flight">
<from>Berlin</from>
<to>Paris</to>
</ns2:getFlightPrice>
</soap:Body>
</soap:Envelope>
Click the "Assertions" tab
Click the "Adds an assertion to this item" button
Select "Schema Compliance" and click "OK"
Check the definition url to validate by and click "OK"
The assertion should appear as valid.
Click the "Adds an assertion to this item" button
Select "XPath Match" and click "OK", this opens the XPath Match configuration wi
ndow
Click "Declare" to generate declarations automatically
declare namespace soap='http://schemas.xmlsoap.org/soap/envelope/';
declare namespace ns2='http://external.services/flight';
Query the "from" field //ns2:getFlightPrice/from
Set the expected result, in this example "Berlin"
Click "Save"
The assertion should appear as valid.
Do the same for the "to" field and check it is Paris.

6 How to check the response


Run the test case, it should now be successful.
Open the test request editor
Click the "Assertions" tab
Add a "Schema Compliance" assertion, to check the response schema
Add a "Not SOAP Fault" assertion, to check the response is not a SOAP fault
Add a "SOAP Response" assertion, to check the response is a SOAP response
Add a "XPath Match" assertion to check the price
XPath Expression
declare namespace soap='http://schemas.xmlsoap.org/soap/envelope/';
declare namespace ns2='http://trip.price.service';
//ns2:getTripPriceResponse/return
Expected Result : 264.98
(3 * 1 * 55 + 2 * 49.99)
Now your test case is complete.

This article extends the basic example described in "Web service testing with so
apUI". It describes how to test and simulate exceptions.
Imagine we want to know the price of a trip from Berlin to Paris. But instead of
typing "Berlin", we enter "Beriln". The FlightPriceService does not know any lo
cation named "Beriln" and throws an exception. In this case, we expect the TripP
riceService to catch this exception and throw his own exception. That is what we
are going to test.
1. Add a test case
Right click on the test suite and select "New TestCase"
Specify a name for the test case, for example "LocationNotFoundException TestCas
e"
Click "OK"
Set a timeout for the test case
2. Add a test request
Right click in the test case editor and select "Append Step" -> "Test Request"
Specify a name for the test request, for example "getTripPrice Test Request"
Click "OK"
Select the operation to invoke for the request "TripPriceServiceFacadeServiceSoa
pBinding -> getTripPrice"
Click "OK"
Select "Add SOAP Response Assertion", "Add Schema Assertion" and "Create optiona
l elements"
Make sure "Add not SOAP Fault Assertion" is not selected, because the exception
we expect is a SOAP fault
Click "OK"
Edit the request
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmln
s:trip="http://trip.price.service">
<soapenv:Header/>
<soapenv:Body>
<trip:getTripPrice>
<trip>
<adults>2</adults>
<duration>3</duration>
<from>Beriln</from>
<rooms>1</rooms>
<to>Paris</to>
</trip>
</trip:getTripPrice>
</soapenv:Body>
</soapenv:Envelope>
Add a "SOAP Fault" assertion
Add a "XPath Match" assertion, to check the faultstring
XPath Expression
declare namespace soap='http://schemas.xmlsoap.org/soap/envelope/';
declare namespace ns1='http://trip.price.service';
//soap:Fault/faultstring
Expected Result
Location Beriln not found

3. Add a standard mock response


See the basic example for more details.
Right click in the test case editor and select "Append Step" -> "Mock Response"
Specify a name for the mock response, for example "getRoomPrice Mock Response"
Click "OK"
Select the "getRoomPrice" operation of the "HotelPriceServiceFacadeServiceSoapBi
nding" interface
Set the port, in this example "8088"
Set the path, in this example "/external-services-0.0.1-SNAPSHOT/webservices/Hot
elPriceService"
Click "OK"
Edit the response price
Set "getTripPrice" as the start step
4. Add a mock response with an exception
Right click in the test case editor and select "Append Step" -> "Mock Response"
Specify a name for the mock response, for example "getFlightPrice Mock Response"
Click "OK"
Select the "getFlightPrice" operation of the "FlightPriceServiceFacadeServiceSoa
pBinding" interface
Set the port, in this example "8088"
Set the path, in this example "/external-services-0.0.1-SNAPSHOT/webservices/Fli
ghtPriceService"
Click "OK"
In the Mock Response editor click the "Creates a SOAP Fault Response" button (re
d question mark)
Overwrite the current response with a fault
Select "LocationNotFoundException" and click "OK"
Edit the fault to set a faultcode and a faultstring
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmln
s:flig="http://external.services/flight">
<soapenv:Body>
<soapenv:Fault>
<faultcode>soap:Server</faultcode>
<faultstring xml:lang="en">Location Beriln not found</faultstring>
<detail>
<flig:LocationNotFoundException/>
</detail>
</soapenv:Fault>
</soapenv:Body>
</soapenv:Envelope>
Set "getTripPrice" as the start step

Now you can run the test case, it should be successfull

You might also like