Updating a SOAP project using a WSDL
When a SOAP project's WSDL changes, SoapUI can use the new definition to:
- Update the port binding
- Add new operations and requests
- Update endpoints in requests
This recipe builds on the previous example to show how SoapUI can help you do this when a new web service operation is added. We then provide a basic test-driven implementation to support the new operation.
Getting ready
The new WSDL defines a createInvoice
operation and can be found in <chapter 1 samples>/soap/invoicev2_impl/wsdl/Invoice_v2.wsdl
.
To save time coding the implementation, you can take either the full service code or just the Java classes you need from <chapter 1 samples>/soap/invoicev2_impl
.
The SoapUI project for this recipe can be found at <chapter 1 samples>/invoice-soap-v2-soapui-project.xml
.
How to do it...
After updating our SOAP project using the new WSDL and SoapUI's Update Definition functionality, we need to add a new failing test for the new createInvoice
operation. Next, we generate an empty web service stub using the new WSDL and the approach shown in the first recipe. Finally, with our failing test, we will provide a basic implementation to pass the test.
- To update our SoapUI project with the new WSDL, right-click on InvoicePortBinding and select Update Definition. Enter the following in the Update Definition window and click on OK:
- Definition URL: This is
<chapter1 samples>/soap/invoicev2_impl/wsdl/invoice_v2.wsdl
. - Tick Recreate existing request with the new schema.
- Leave the rest of the checkboxes at their default values.
- Definition URL: This is
- Click on Yes on the Update Definition with new endpoint popup (although this didn't actually update the endpoint for me!). This should result in
InvoicePortBinding
now showing thecreateInvoice
operation and request. - Next, let's add a new
TestCase
option forcreateInvoice
calledTestCase – Create Invoice
. Also, change the order so thatTestCase – Create Invoice
is run beforegetInvoice TestCase
. - Add a new
TestStep
option underTestCase – Create Invoice
calledcreateInvoice
, and select InvoicePortBinding > createInvoice in the operation popup and just accept default value in the Add Request To TestCase popup.Tip
Check Endpoints
Make sure both
TestSteps
are now pointing to the new endpointhttp://localhost:9002/ws/invoice/v2
. Update Definition only seems to update the request endpoints under the port binding. - Generate a new empty web service for
invoice_v2.wsdl
as per the previous recipe, using Tools | Apache CXF:- WSDL Location:
invoice_v2.wsdl
. - Change
v1
tov2
in all the paths, packages, and Custom Args. - Copy
invoice_v2.wsdl
to the root of your classes' folder, for example,<chapter1 samples>/soap/invoicev2/target/classes
.
- WSDL Location:
- Start the generated invoice v2 server:
cd <chapter1 samples>/soap/invoicev2/target/classes java ws.invoice.v2.InvoicePortType_InvoicePort_Server
- If you now run the tests:
- The
createInvoice
TestStep
operation will succeed since it doesn't have anyAssertions
. - The
getInvoice TestStep
operation will fail as expected because our previous implementation is not part of the newly generated invoice v2 service code.
- The
- Next, let's add
Assertion
to test thecreateInvoice
operation. Insert the same invoice values as we did in thegetInvoice
TestStep
operation into the request of thecreateInvoice TestStep
operation and addXPath Assertion
to check whether the acknowledgmentinvoiceNo
is 12345:Name: AcknowledgementShouldContainInvoiceNo12345 XPath: declare namespace ns1='http://soapui.cookbook.samples/schema/invoice'; //ns1:Acknowledgement[1]/ns1:invoiceNo[1] Expected Value: 12345
- If we now rerun
TestCase
:- The
createInvoice TestStep
operation will still pass, again thanks to the Apache CXF-generated code passing through theinvoiceNo
from the request to the response. - The
getInvoice TestStep
operation will now not pass as expected.
- The
- Providing a simple service implementation to pass the tests by storing invoice details between requests and allowing them to be retrieved involves a little more coding than in the previous recipe. So to stay more in the scope of SoapUI, we can take what we need from a completed example service implementation in this chapter's samples. If you have generated the new empty web service stub in step 5, then all that you will need to take are:
InvoicePortImpl.java
: This provides the main functionality.Invoice.java
: This is a JavaBean to store invoice details.
More information on these is provided in the next section.
- Next, recompile and restart the server.
- Rerun the tests, and both should now pass!
How it works...
The main learning of this recipe is how to use the Update Definition functionality, and what it does and doesn't update for you. Like in the previous recipe, we have only used a very basic service implementation just to pass the tests. The main points of the service implementation are as follows:
- When SoapUI makes a request to the
createInvoice
operation, theInvoicePortImpl.createInvoice
method extracts the invoice details from the request and stores them (usingInvoice.java
) in aHashMap
keyed oninvoiceNo
. TheinvoiceNo
value is then returned in the acknowledgment response. - When SoapUI makes a request to the
getInvoice
operation, theInvoicePortImpl.getInvoice
method uses theinvoiceNo
value in the request to retrieve the invoice details from theHashMap
(held inInvoice.java
) and return them in the response to SoapUI.
There's more...
Here, we have developed a very simple non-persistent dynamic web service stub. Chapter 3, Developing and Deploying Dynamic REST and SOAP Mocks, also shows how to use in-memory H2 databases to provide a non-persistent, dynamic REST and SOAP mock service functionality. If you would like to persist the request data, then Chapter 9, Data-driven Load Testing With Custom Datasources, uses a SOAP service stub with a simple H2 database backend to persist data.
For Pro version users, the next recipe continues the SOAP web service stub journey by showing how SoapUI WSDL refactoring can help manage more complicated service definition updates.