
SoapUI Cookbook
By :

SoapUI is often used to retrofit tests around web services that are already at least partially developed. To follow a test-first or test-driven development (TDD) approach requires that we first set up failing tests and then provide a service implementation in order to pass them. In this recipe, we'll see how SoapUI can be used to facilitate test-first development for the invoice web service generated in the previous recipe.
We'll need the WSDL from the previous recipe to set up our SoapUI project (<chapter1 samples>/soap/invoicev1/wsdl/invoice_v1.wsdl
).
The Java code for the completed web service implementation can be found at <chapter1 samples>/soap/invoicev1_impl
.
The project can be found at <chapter1 samples>/invoice-soap-v1-soapui-project.xml
.
Eclipse setup
Optionally, it is very easy to set up an Eclipse project to make light work of the test, edit, compile, and run cycle. First, import the sample code and then run the service as a standard Java application.
Firstly, we'll set up a couple of simple failing tests to assert what we expect back from the getInvoice
operation and then provide basic implementation to pass them. Next, we'll update the invoice WSDL definition to provide an additional createInvoice
operation, write new failing tests, and finally provide basic code to pass those. Perform the following steps:
PortBinding
, Test Suite
, TestCase
, and Test Request TestStep
, right-click on your Workspace
and select New SOAP Project. In the window, enter/select the following and click on OK:InvoiceService
chapter1 samples>/soap/invoicev1/wsdl/invoice_v1.wsdl
TestSuite
name as InvoicePortBinding TestSuite
in the pop up and click on OK. All expected SoapUI test artifacts should now be generated in your project.getInvoice
request to return. Under the first TestStep
option, double-click on getInvoice
and you should see the SOAP request:<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:inv="http://soapui.cookbook.samples/schema/invoice"> <soapenv:Header/> <soapenv:Body> <inv:getInvoice> <inv:invoiceNo>?</inv:invoiceNo> </inv:getInvoice> </soapenv:Body> </soapenv:Envelope>
invoiceNo
(?
) value to something more memorable, for example, 12345
.<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"> <S:Body> <InvoiceDocument xmlns="http://soapui.cookbook.samples/schema/invoice"> <invoiceNo>12345</invoiceNo> <company/> <amount>0.0</amount> </InvoiceDocument> </S:Body> </S:Envelope>
Assertions
to specify the invoice property values we expect to see:invoiceNo
= 12345
company
= Test Company
amount
= 100.0
Since we're dealing with SOAP XML, let's add 3 XPath
Assertions
to check these values in the response. SoapUI Pro users will find this easy, thanks to the convenient XPath
builder. Open source users can either be 'hardcore' and write them from scratch or just copy the details provided.
XPath Help
Even the Pro version's XPath builder is of less use when you cannot directly retrieve a response XML to build from, that is, when there is no service at all! As a workaround, you can get SoapUI to generate a sample response XML by going to Add Step | SOAP Mock Response TestStep
from the TestCase
, and then copy the response XML into a helpful XPath tool to write the XPath expression, for example, http://www.freeformatter.com/xpath-tester.html. Paid-for tools such as XML Spy will also help a lot in these areas. You may also find http://www.w3schools.com/XPath/xpath_syntax.asp helpful.
So let's add 3 XPath Assertions
. Edit the REST Request
TestStep
, under the Assertions tab and right-click on Add Assertion and add a new XPath Assertion
to check the response's invoiceNo=12345
, company=Test Company
, and amount=100.0
:
Response |
Assertion name |
XPath Expression |
Expected Result |
---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
Have a look at the following screenshot for better clarity:
Running the TestCase
should now fail 2 of the assertions. Note that InvoiceNoShouldBe12345
will work, thanks to Apache CXF passing through the request's invoiceNo
to the response (see InvoicePortImpl.java
)! It is still worth asserting the invoiceNo
value, as it is a requirement.
Server timed out?
If you instead see a connection refused
error, then check whether your server hasn't exited after 5 minutes. It's easy to change this timeout (see the previous recipe).
Now, we can add a very basic service implementation to pass this test. We just need to implement the getInvoice(…)
method in InvoicePortImpl.java
. The simplest implementation option is to just edit InvoicePortTypeImpl.java
and hardcode the expected values:
try { java.lang.String companyValue = "Test Company"; company.value = companyValue; java.lang.Double amountValue = 100.0d; amount.value = amountValue; } catch (java.lang.Exception ex) { ex.printStackTrace(); throw new RuntimeException(ex); }
TDD
Strictly speaking, we should first write a unit test before implementing the method, for example, using JUnit.
Next, recompile this and restart the server:
cd <chapter1 samples>/soap/invoicev1 javac src/main/java/ws/invoice/v1/*.java -d target/classes/
And start it again:
cd <chapter1 samples>/soap/invoicev1/target/classes java ws.invoice.v1.InvoicePortType_InvoicePort_Server
Rerun TestCase
, which should now pass!
This recipe builds on all the same JAX-WS web service code explained in the previous recipe. This time, we add a very simple stub implementation to return the minimum necessary to pass the test. For those who haven't seen JAX-WS before, the use of the javax.xml.ws.Holder
wrapper object means that we don't have to explicitly set the invoiceNo,
as it is passed through the request (for more information, see http://tomee.apache.org/examples-trunk/webservice-holder/README.html).
As mentioned in the previous recipe, SoapUI mocks (see Chapter 3, Developing and Deploying Dynamic REST and SOAP Mocks) can often provide a convenient and often quicker alternative if all you need is a disposable test version of your web service with basic functionality. Also, if you want your web service stub to be the basis for ongoing development, then you may want to consider using a build framework like Gradle or Maven to manage the build, deploy, and test cycle. Chapter 5, Automation and Scripting, looks at different ways to use build frameworks and scripts to run SoapUI tests (and mocks) after your web service is built and deployed. If your stub implementations become more complicated, you may also want unit tests.
The SOAP web service stub journey continues in the next recipe where we use SoapUI to help us update the project, tests, and services to add a createInvoice
operation.
Change the font size
Change margin width
Change background colour