SoapUI Tutorial: SOAP Web Service Testing Step by Step
Banks, insurers, airlines, telecom operators and government systems still run on SOAP web services, and SoapUI is the tool their QA teams use to test them. In this SoapUI tutorial you’ll install SoapUI, import a real WSDL, send SOAP requests, add assertions (including XPath and SOAP Fault checks), build a test suite and even find a real bug in a public SOAP service. No coding needed.
testrunner. ReadyAPI is the paid version with extra features.Where You’ll Meet SOAP in Real Projects
GetAccountBalance and FundTransfer to the mobile banking middleware. Insurance: agent portals call CreateQuote and IssuePolicy. Telecom: billing systems expose GetBillSummary. Travel: airline reservation systems and GDS integrations. Many of these were built 10 to 20 years ago and are still business-critical.Service companies working for these clients regularly ask for “SoapUI” in QA job descriptions. If you’ve only tested REST, this lesson closes the gap. Background: REST vs SOAP vs GraphQL.
Key SOAP Terms Before You Start
| Term | Meaning |
|---|---|
| WSDL | Web Services Description Language: the XML contract listing operations, messages, types and the endpoint URL |
| Operation | A function the service offers, e.g. Add, GetBalance |
| Envelope / Header / Body | The parts of every SOAP message |
| SOAP Fault | The standard error element inside Body (faultcode, faultstring, detail) |
| Binding | How messages are sent: SOAP 1.1 or SOAP 1.2 |
| Namespace | A URI that qualifies element names, e.g. xmlns:tem="http://tempuri.org/" |
| SOAPAction | HTTP header (SOAP 1.1) naming the operation |
| XSD | XML Schema defining the data types |
Step 1: Install SoapUI
- Download SoapUI Open Source from soapui.org (Windows, macOS, Linux). It’s free; ReadyAPI is the commercial edition.
- Install and launch it. The left panel is the Navigator (project tree); the main area opens editors for requests and tests.
Step 2: Create a SOAP Project from a WSDL
We’ll use a free public demo calculator service:
http://www.dneonline.com/calculator.asmx?WSDL
- File → New SOAP Project.
- Project name:
Calculator. Initial WSDL: paste the URL above. - Keep Create Requests ticked. Click OK.
- SoapUI reads the WSDL and creates two bindings,
CalculatorSoap(SOAP 1.1) andCalculatorSoap12(SOAP 1.2), each with four operations: Add, Subtract, Multiply, Divide, and a sample request “Request 1” under each.
Public demo services can be slow or occasionally offline. If it doesn’t respond, try again later; the steps are identical for your company’s WSDL.
Step 3: Send Your First SOAP Request
Expand CalculatorSoap → Add and double-click Request 1. SoapUI generated this template:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:tem="http://tempuri.org/">
<soapenv:Header/>
<soapenv:Body>
<tem:Add>
<tem:intA>?</tem:intA>
<tem:intB>?</tem:intB>
</tem:Add>
</soapenv:Body>
</soapenv:Envelope>
Replace the ? with 5 and 7, then click the green Submit arrow. The response:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" ...>
<soap:Body>
<AddResponse xmlns="http://tempuri.org/">
<AddResult>12</AddResult>
</AddResponse>
</soap:Body>
</soap:Envelope>
Use the tabs on the response side: XML (body), Raw (HTTP status and headers: HTTP/1.1 200 OK, Content-Type: text/xml) and the time in milliseconds at the bottom.
The same call with cURL, so you see what SoapUI sends under the hood:
curl -i -X POST "http://www.dneonline.com/calculator.asmx" \
-H "Content-Type: text/xml; charset=utf-8" \
-H 'SOAPAction: "http://tempuri.org/Add"' \
-d '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/"><soapenv:Body><tem:Add><tem:intA>5</tem:intA><tem:intB>7</tem:intB></tem:Add></soapenv:Body></soapenv:Envelope>'
Content-Type: text/xml plus a separate SOAPAction header. SOAP 1.2 uses Content-Type: application/soap+xml; action="..." and the namespace http://www.w3.org/2003/05/soap-envelope. Try the same operation under CalculatorSoap12 to see the difference in the Raw tab.Step 4: Build a Test Suite
Requests under the interface are for exploring. Real tests live in test suites:
- Right-click the
Addrequest → Add to TestCase → create TestSuiteCalculator Regressionand TestCaseAdd - positive. - The request becomes a TestStep. Add more steps for Subtract, Multiply and Divide the same way.
| Level | Example | Holds |
|---|---|---|
| Project | Calculator | Interfaces (WSDL), test suites, project properties |
| TestSuite | Calculator Regression | Related test cases |
| TestCase | Divide – negative | Ordered test steps (one scenario) |
| TestStep | SOAP Request, Properties, Property Transfer, Groovy Script, Delay, Conditional Goto | One action |
Step 5: Add Assertions
Open a test step, click the Assertions tab at the bottom, then +:
| Assertion | Checks | Example |
|---|---|---|
| SOAP Response | Response is a valid SOAP message | Always add it |
| Not SOAP Fault | No Fault in the body | Positive cases |
| SOAP Fault | A Fault is present | Negative cases |
| Contains / Not Contains | Text or regex in the response | <AddResult>12</AddResult>; Not Contains “Exception” |
| XPath Match | Value at an XPath equals expected | See below |
| Schema Compliance | Response matches the WSDL/XSD types | Contract check |
| Response SLA | Response time under N ms | 2000 ms |
| Valid HTTP Status Codes | Status is in a list | 200 |
| Script Assertion | Custom Groovy logic | Complex rules |
XPath Match assertion
Click Declare to let SoapUI add the namespaces, then write:
declare namespace soap='http://schemas.xmlsoap.org/soap/envelope/';
declare namespace ns1='http://tempuri.org/';
//ns1:AddResponse/ns1:AddResult
Expected result: 12. Namespace-free alternative that’s handy when prefixes change: //*[local-name()='AddResult'].
<ErrorCode>1203</ErrorCode>. XPath Match checks the value of the exact element, which is what a bank auditor would expect for an amount field.Step 6: Negative Tests and SOAP Faults
Create a TestCase Divide - negative and send intA = 5, intB = 0. The real response:
HTTP/1.1 500 Internal Server Error
Content-Type: text/xml; charset=utf-8
X-AspNet-Version: 2.0.50727
X-Powered-By: ASP.NET
<soap:Fault>
<faultcode>soap:Server</faultcode>
<faultstring>System.Web.Services.Protocols.SoapException: Server was unable to process request.
---> System.OverflowException: Arithmetic operation resulted in an overflow.
at Calculator.Divide(Int32 intA, Int32 intB) in G:\PleskVhosts\...\Calculator.asmx:line 19 ...</faultstring>
<detail />
</soap:Fault>
Add assertions SOAP Fault and Valid HTTP Status Codes = 500. Then look closer, as a tester should. This demo service shows three issues you’d report in a real project:
- Information disclosure (security): the faultstring exposes a .NET stack trace, internal class names and the server’s file path. The
X-AspNet-Versionheader reveals the framework version. (OWASP API8, Security Misconfiguration.) - Wrong fault code: dividing by zero is a client input problem, so it should be
soap:Clientwith a clear message such as “intB must not be 0”, notsoap:Server. - Misleading message: “overflow” instead of “division by zero”.
More negative cases to add: non-numeric input (abc, returns a fault), integer overflow (2147483647 + 1, also a fault), missing elements, empty body, wrong SOAPAction, wrong namespace, and malformed XML. Add a Not Contains assertion for “Exception” and “line” on every negative case to catch stack-trace leaks automatically.
Step 7: Properties: Stop Hardcoding Values
Define values once and reuse them with ${...} expansions:
- Project property
endpoint = http://www.dneonline.com/calculator.asmx, then set the request endpoint to${#Project#endpoint}, so switching environments is one change. - TestCase property
a = 20,b = 5, then the request uses<tem:intA>${#TestCase#a}</tem:intA>. - Expected values in XPath assertions can also use properties.
Passing values between steps (for example a session id from Login into GetBalance) uses Property Transfer, covered in the next lesson with REST examples: SoapUI REST and Data-Driven Testing.
Step 8: Run Suites and Read Results
- Double-click the TestSuite and press the green Run button; each case turns green or red.
- Open a failed step: the assertion panel shows exactly which assertion failed and why.
- The TestCase Log shows timings per step; Raw tabs show the full HTTP exchange.
Command line and CI
# SoapUI ships testrunner.sh / testrunner.bat in its bin folder
./testrunner.sh -s"Calculator Regression" -r -j -f ./reports Calculator-soapui-project.xml
# -s test suite to run -r print summary report
# -j JUnit-style XML reports -f output folder
# -P endpoint=https://qa.bank.example/CoreBanking override a project property
The whole project is one XML file (Calculator-soapui-project.xml), so keep it in Git and run it in Jenkins or GitHub Actions.
Testing SOAP Without SoapUI
SOAP is just XML over HTTP POST, so Postman (raw XML body + headers), cURL and Playwright can call it too. Playwright example from the same service:
import { test, expect } from '@playwright/test';
const URL = 'http://www.dneonline.com/calculator.asmx';
const envelope = (op: string, a: number | string, b: number | string) =>
`<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/">
<soapenv:Body><tem:${op}><tem:intA>${a}</tem:intA><tem:intB>${b}</tem:intB></tem:${op}></soapenv:Body>
</soapenv:Envelope>`;
async function call(request: any, op: string, a: number | string, b: number | string) {
return request.post(URL, {
headers: { 'Content-Type': 'text/xml; charset=utf-8', SOAPAction: `"http://tempuri.org/${op}"` },
data: envelope(op, a, b),
});
}
test('Multiply 6 x 7 = 42', async ({ request }) => {
const res = await call(request, 'Multiply', 6, 7);
expect(res.status()).toBe(200);
expect(await res.text()).toMatch(/<MultiplyResult>42<\/MultiplyResult>/);
});
test('Divide by zero returns a SOAP Fault', async ({ request }) => {
const res = await call(request, 'Divide', 5, 0);
expect(res.status()).toBe(500);
expect(await res.text()).toContain('<soap:Fault>');
});
Use SoapUI when the team relies on WSDL-driven work and non-coders; use code when SOAP tests must live alongside REST and UI tests in one framework.
SOAP Testing Checklist
- WSDL loads; operations match the specification.
- Every operation: valid input → correct values (XPath), Not SOAP Fault, schema compliant, within SLA.
- Invalid input → SOAP Fault with correct faultcode (Client vs Server) and a useful message.
- No stack traces, file paths or versions in faults or headers.
- Both SOAP 1.1 and 1.2 bindings if both are published.
- WS-Security: unsigned, expired or tampered messages are rejected.
- XML attacks: XXE and very large or deeply nested XML are rejected.
Interview Questions: SoapUI and SOAP Testing
What is SoapUI?
An open-source tool for functional testing of SOAP and REST APIs. It creates requests from WSDL or OpenAPI definitions, supports assertions, properties, test suites, Groovy scripting, data-driven tests and command-line execution. ReadyAPI is the commercial version.
What is a WSDL?
An XML document describing a SOAP service: its operations, input and output messages, data types (XSD), bindings (SOAP 1.1/1.2) and endpoint address. SoapUI uses it to generate request templates.
What is the hierarchy of a SoapUI project?
Project, then TestSuite, then TestCase, then TestStep. The project also holds interfaces generated from WSDL/OpenAPI and properties at each level.
Which assertions do you use in SoapUI?
SOAP Response, Not SOAP Fault or SOAP Fault, Contains/Not Contains, XPath Match, XQuery Match, Schema Compliance, Response SLA, Valid HTTP Status Codes and Script Assertion for custom Groovy logic.
What is an XPath Match assertion?
It evaluates an XPath expression against the response (with declared namespaces) and compares the result with an expected value, for example //ns1:AddResult equals 12.
How are errors returned in SOAP?
As a SOAP Fault element inside the Body with faultcode, faultstring and optional detail, usually with HTTP status 500. SOAP 1.2 uses Code, Reason and Detail elements.
What is the difference between SOAP 1.1 and SOAP 1.2?
SOAP 1.1 uses Content-Type text/xml with a separate SOAPAction header and the schemas.xmlsoap.org envelope namespace. SOAP 1.2 uses application/soap+xml with the action as a parameter, the w3.org 2003/05 namespace, and a different fault structure.
How do you run SoapUI tests in CI?
With the testrunner command-line tool included with SoapUI, passing the project file, suite name and options for JUnit reports and property overrides. CI tools such as Jenkins then publish the reports.
What is the difference between SoapUI and ReadyAPI?
SoapUI Open Source is free and covers core functional testing. ReadyAPI is commercial and adds data-source steps without scripting, advanced reporting, service virtualisation, performance testing and team collaboration features.
What would you check in a SOAP Fault during testing?
The correct HTTP status, the fault code (Client for bad input, Server for server errors), a clear and safe message, no stack traces or internal paths, and the detail element if the contract defines error codes.