Book Image

SoapUI Cookbook

By : Rupert Anderson
Book Image

SoapUI Cookbook

By: Rupert Anderson

Overview of this book

Table of Contents (19 chapters)
SoapUI Cookbook
Credits
About the Author
Acknowledgments
About the Reviewers
www.PacktPub.com
Preface
Index

Developing a SOAP web service test-first


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.

Getting ready

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.

Tip

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.

How to do it...

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:

  1. To create the SoapUI project and generate the initial 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:

    • Project Name: InvoiceService

    • Initial WSDL: chapter1 samples>/soap/invoicev1/wsdl/invoice_v1.wsdl

    • Leave Create Requests ticked and also tick Create TestSuite

  2. In the Generate TestSuite window, select the following options and click on OK:

    • Leave Style as One TestCase for Each Operation

    • Change Request Content to Use existing Requests in Interface

  3. Accept the suggested 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.

  4. Now, we can write a simple failing test to assert what we expect a successful 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>
  5. Change the invoiceNo (?) value to something more memorable, for example, 12345.

  6. Now, start the stub invoice service generated in the previous recipe and submit the request by clicking on the green arrow. You should see a stubbed response, like the one shown in the following code:

    <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>
  7. Next, let's create some SoapUI 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.

Tip

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

invoiceNo=12345

InvoiceNoShouldBe12345

declare namespace ns1='http://soapui.cookbook.samples/schema/invoice';

//ns1:InvoiceDocument[1]/ns1:invoiceNo[1]

12345

company=Test Company

Invoice12345ShouldHaveCompanyNameOfTestCompany

declare namespace ns1='http://soapui.cookbook.samples/schema/invoice';

//ns1:InvoiceDocument[1]/ns1:company[1]

Test Company

amount=100.0

Invoice12345ShouldHaveAmountOf100.0

declare namespace ns1='http://soapui.cookbook.samples/schema/invoice';

//ns1:InvoiceDocument[1]/ns1:amount[1]

100.0

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.

Tip

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);
}

Tip

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!

How it works...

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).

There's more...

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.

See also