API Protocols: GraphQL, SOAP, WebSocket, MCP

SOAP API Testing: How to Test WSDL Web Services

Rishi GauravUpdated Aug 20, 202613 min read

Quick answer

SOAP API testing means sending XML envelopes to the operations a WSDL describes and asserting on the response: namespaced XPath for values, the SOAP Fault code and detail for errors, and the WSDL contract for drift. Cover happy paths, faults, XML Schema boundary values and XML attacks such as XXE, and run the suite in CI alongside REST tests.

Reviewed by Parveen Kumari

Share:
SOAP API testing workflow from WSDL import to CI quality gate

Part of the API Protocols: GraphQL, SOAP, WebSocket, MCP hub. Start with the pillar guide: REST vs GraphQL vs gRPC testing.

SOAP API testing means sending XML envelopes to the operations a WSDL describes and checking what comes back: element values with namespaced XPath, SOAP Faults for error cases, the constraints in the XML Schema, security behaviour, and changes to the WSDL contract itself. It is part of our protocols hub; for how SOAP compares with REST, GraphQL and gRPC testing, start with REST vs GraphQL vs gRPC testing.

SOAP is not greenfield technology, but it is far from gone. Core banking, payment gateways, insurance policy and claims systems, healthcare integrations and government service buses still expose SOAP services, and new REST APIs often wrap them. If you test those systems, SOAP testing is part of the job. This guide covers how SOAP works from a tester's point of view, how it differs from REST, a step-by-step approach with working code, the test cases to cover, tools, CI/CD and what changes in regulated industries.


In this guide

  1. What is SOAP API testing?
  2. SOAP vs REST API testing
  3. How to test a SOAP API, step by step
  4. SOAP test cases to cover
  5. SOAP API testing tools
  6. Running SOAP tests in CI/CD
  7. SOAP testing in banking, insurance and other regulated industries
  8. Testing SOAP with Shift-Left API
  9. FAQ

What is SOAP API testing?

A SOAP service exchanges XML messages wrapped in an envelope: an optional Header (for things like security tokens) and a Body containing the operation and its parameters. The service is described by a WSDL (Web Services Description Language) file, which lists the operations, the message types (defined in XML Schema), the bindings (SOAP 1.1 or 1.2) and the endpoint address.

A minimal request and response:

<!-- request -->
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
               xmlns:acc="http://example.com/accounts">
  <soap:Body>
    <acc:GetBalance>
      <acc:AccountId>12345678</acc:AccountId>
    </acc:GetBalance>
  </soap:Body>
</soap:Envelope>

<!-- response -->
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
               xmlns:acc="http://example.com/accounts">
  <soap:Body>
    <acc:GetBalanceResponse>
      <acc:Balance currency="EUR">1520.75</acc:Balance>
    </acc:GetBalanceResponse>
  </soap:Body>
</soap:Envelope>

When something goes wrong, the service returns a SOAP Fault instead of a normal body, usually with HTTP 500:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <soap:Fault>
      <faultcode>soap:Client</faultcode>
      <faultstring>Account not found</faultstring>
      <detail><code>ACC-404</code></detail>
    </soap:Fault>
  </soap:Body>
</soap:Envelope>

Two version details trip people up. SOAP 1.1 uses Content-Type: text/xml and a separate SOAPAction header; SOAP 1.2 uses application/soap+xml with the action as a content-type parameter, and its fault structure uses Code/Reason elements. Check which binding the WSDL declares before writing assertions.

SOAP vs REST API testing

ConcernRESTSOAP
ContractOpenAPI (optional in practice)WSDL with XML Schema (required)
EndpointsMany resource URLs and methodsOne endpoint per service, many operations
PayloadUsually JSONXML envelope
Success / failure signalHTTP status codeNormal body vs SOAP Fault (often HTTP 500)
Value assertionsJSON pathXPath, with namespaces
Negative cases400/401/403/404/409/422Fault code, fault string and detail
Contract driftOpenAPI diffWSDL / XSD diff
Message-level securityUsually transport (TLS, OAuth)Transport, or WS-* message signing and encryption
Typical performance issueSlow endpointsLarge envelope parsing and serialisation

The habits that break when REST testers move to SOAP: treating HTTP 500 as "server down" when it is a well-formed fault you should assert on, writing XPath without namespaces (which silently matches nothing), and asserting on fault strings that are written for humans rather than on fault codes and detail elements.

How to test a SOAP API, step by step

1. Read the WSDL. List the operations, their input and output messages, and the XML Schema types with their restrictions (minLength, maxLength, pattern, enumeration, minInclusive, maxInclusive). Those restrictions are your boundary-value test cases.

2. Build a valid envelope per operation. Generate it from the WSDL (SoapUI, zeep, CXF or a platform importer) rather than hand-typing XML.

3. Send it correctly. POST to the endpoint with the right content type and SOAPAction for the binding.

4. Assert with namespaced XPath. Register the namespaces from the WSDL and assert on element values, attributes and counts.

5. Assert on faults for negative cases. Check the fault code and detail, not just the HTTP status.

6. Check response time and size, especially for operations that return lists or documents.

A plain Python version with requests and lxml:

# tests/test_accounts_soap.py
import requests
from lxml import etree

URL = "https://accounts.staging.example.com/AccountService"
NS = {"soap": "http://schemas.xmlsoap.org/soap/envelope/",
      "acc": "http://example.com/accounts"}
HEADERS = {"Content-Type": "text/xml; charset=utf-8",
           "SOAPAction": "http://example.com/accounts/GetBalance"}

def envelope(account_id):
    return f"""<soap:Envelope xmlns:soap="{NS['soap']}" xmlns:acc="{NS['acc']}">
      <soap:Body><acc:GetBalance><acc:AccountId>{account_id}</acc:AccountId></acc:GetBalance></soap:Body>
    </soap:Envelope>"""

def post(body):
    r = requests.post(URL, data=body.encode(), headers=HEADERS, timeout=10)
    return r, etree.fromstring(r.content)

def test_get_balance_returns_amount_and_currency():
    r, doc = post(envelope("12345678"))
    assert r.status_code == 200
    balance = doc.xpath("//acc:GetBalanceResponse/acc:Balance", namespaces=NS)
    assert len(balance) == 1
    assert float(balance[0].text) >= 0
    assert balance[0].get("currency") == "EUR"

def test_unknown_account_returns_client_fault():
    r, doc = post(envelope("00000000"))
    assert r.status_code == 500                      # faults usually ride on 500
    assert doc.xpath("string(//soap:Fault/faultcode)", namespaces=NS).endswith("Client")
    assert doc.xpath("string(//soap:Fault/detail/code)", namespaces=NS) == "ACC-404"

Generate test cases from your spec (free)

Free, runs in your browser, no sign-up needed.

If you prefer a typed client, Python's zeep reads the WSDL and builds the envelope for you:

from zeep import Client
from zeep.exceptions import Fault
import pytest

client = Client("https://accounts.staging.example.com/AccountService?wsdl")

def test_get_balance_typed():
    result = client.service.GetBalance(AccountId="12345678")
    assert result.currency == "EUR"

def test_unknown_account_fault_typed():
    with pytest.raises(Fault) as e:
        client.service.GetBalance(AccountId="00000000")
    assert "not found" in e.value.message.lower()

For a quick manual check, curl is enough:

curl -s -X POST "$URL" \
  -H 'Content-Type: text/xml; charset=utf-8' \
  -H 'SOAPAction: http://example.com/accounts/GetBalance' \
  --data @get-balance.xml | xmllint --format -

SOAP test cases to cover

Functional

  • Happy path for every operation, asserting on the elements the business cares about.
  • Optional elements present and absent; repeated elements (maxOccurs) with zero, one and many items.
  • Each value in an enumeration.

Negative and faults

  • Missing required elements, wrong types, and values outside schema restrictions (one below and one above each boundary).
  • Unknown identifiers and business-rule violations, asserting on the fault code and detail.
  • Malformed XML and wrong namespaces, which should produce a client fault, not a stack trace.
  • The wrong SOAPAction for an operation, which should be rejected, not routed to a different operation.

Security

  • XML External Entities (XXE): a DOCTYPE declaring an external entity must be rejected or ignored, never resolved. See the OWASP XXE Prevention Cheat Sheet.
  • Entity expansion ("billion laughs") and oversized payloads: the service should refuse them quickly.
  • Authentication and authorization: missing, expired and other users' credentials; one customer must not read another's account by changing an ID in the body.
  • Fault leakage: faults must not contain stack traces, SQL or internal hostnames.

Contract

  • Diff the WSDL and imported XSDs on every change; removed operations, removed or retyped elements, and new required elements are breaking. A typed client generated from the old WSDL failing to compile against the new one is a cheap breaking-change check.

SOAP API testing tools

ToolLicenceWSDL-drivenMessage signing / encryptionCI-friendlyBest for
SoapUI Open SourceFree (EUPL)YesPartialVia command-line runner or Maven pluginWSDL-first suites
ReadyAPICommercialYesYesYesRegulated estates needing message security and reporting
KarateFree (MIT)Manual envelopesManualYesMixed SOAP and REST in one suite
REST AssuredFree (Apache 2.0)Manual envelopesManualYesJVM teams already using it for REST
Apache CXF (wsdl2java)Free (Apache 2.0)YesYesYesGenerating a typed Java client to test against
zeep (Python)Free (MIT)YesPartialYesPython test suites
PostmanFreemiumWSDL importNoVia NewmanAd-hoc probing
Shift-Left APICommercial (free developer licence)YesNoYesGenerated SOAP, REST and GraphQL suites in one CI gate

Testing SOAP in Postman. Postman sends SOAP as a POST with an XML body and can import a WSDL to create requests. That covers plain SOAP well. Signed or encrypted messages and generating negative cases from the schema need extra scripting or a dedicated tool. For a comparison of the two most common SOAP tools, see ReadyAPI vs Postman.

Practice services. Public demo SOAP services (calculators, temperature converters and similar) are handy for learning, but they are run by third parties and can change or vanish. For anything repeatable, mock your own WSDL locally or use your integration partner's sandbox.

Running SOAP tests in CI/CD

SOAP tests belong in the same pipeline as REST tests, with the same gate. A minimal GitHub Actions job that flags WSDL changes and runs the suite:

# .github/workflows/soap-tests.yml
name: SOAP tests
on: [pull_request]
jobs:
  soap:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with: { fetch-depth: 0 }
      - name: Contract drift (WSDL and XSD)
        run: |
          git diff --exit-code origin/main -- contracts/AccountService.wsdl contracts/*.xsd \
            || echo "::warning::WSDL changed - review for breaking changes"
      - uses: actions/setup-python@v5
        with: { python-version: '3.12' }
      - run: pip install pytest requests lxml zeep
      - run: pytest tests/ -q --junitxml=soap-results.xml
        env: { SOAP_URL: '${{ vars.STAGING_SOAP_URL }}' }

Keep destructive and load scenarios against non-production environments, and publish JUnit results so failures show up next to the pull request.

SOAP testing in banking, insurance and other regulated industries

SOAP persists where systems are critical, heavily integrated and expensive to re-validate: core banking, payment settlement gateways, insurance policy administration and claims, healthcare integration engines and government service buses. A single core-banking WSDL can expose hundreds of operations consumed by dozens of systems, so changing the contract has a large blast radius and teams stay conservative. New REST services usually wrap or orchestrate the SOAP back ends, so SOAP and REST coexist, often in the same transaction.

Free PDF + code examples

OpenAPI to Test Generation Template Pack

Go from OpenAPI spec to full test coverage. Includes sample specs, example generated tests, edge case patterns, and CI/CD integration guides.

Download Free

Three things change for testers in these environments:

  • Contract stability matters more than speed. WSDL drift tests and consumer notification are the highest-value checks, because a broken contract affects many downstream systems at once.
  • Message-level security is common. Signed and encrypted messages and token profiles are frequent; make sure your tool supports exactly the profile the service uses, or test that layer with one that does.
  • Where the WSDL goes is a security question. A WSDL describes the surface of regulated data. Uploading it to a cloud tool, or to a cloud AI model for test generation, may breach internal policy or data-residency rules. Many teams need test generation that runs inside their own boundary; our on-prem API testing buyer checklist covers how to evaluate that. Industry specifics are on the banking and insurance pages.

Testing SOAP with Shift-Left API

Shift-Left API's SOAP and WSDL testing imports a WSDL (file or URL), resolves its operations and types, and generates functional, negative and boundary tests from the schema restrictions, alongside REST and GraphQL in the same project and CI gate. Tests run through first-party GitHub Actions, Jenkins and Azure DevOps integrations or the public REST API from any other CI, and the runner writes JUnit XML and gates the build on pass rate. The paid API security testing add-on (included in the trial) adds checks such as calling an operation under the wrong SOAPAction. AI generation can use a self-hosted model on Trial and Enterprise, so a WSDL does not have to leave your network.

Limits to plan around: it does not build or sign WS-* message-security headers and does not send custom SOAP envelope headers, and its XSD assertion checks XML well-formedness rather than validating against the schema. Use a tool from the table above for those layers. You can try SOAP, REST and GraphQL testing with a free developer licence.


SOAP API testing FAQ

What is SOAP API testing?

SOAP API testing verifies a SOAP web service by sending XML envelopes to the operations its WSDL describes and checking the responses: element values via XPath, SOAP Faults for error cases, schema constraints, security behaviour and contract changes in the WSDL. It is API testing with an XML and contract-first flavour.

How do you test a SOAP API?

Import or read the WSDL to find operations and message types, build a request envelope for each operation, send it as an HTTP POST with the right SOAPAction or content type, and assert on namespaced XPath values, fault codes and response times. Then add negative, boundary and security cases and run the suite in CI.

How is SOAP API testing different from REST API testing?

SOAP uses XML envelopes and one endpoint per service described by a WSDL; REST uses many resource URLs, usually JSON, described by OpenAPI. SOAP errors arrive as SOAP Faults, often with HTTP 500, so tests assert on the fault rather than the status code, and use XPath with namespaces instead of JSON paths.

Can you test SOAP APIs in Postman?

Yes. Postman sends SOAP as an HTTP POST with an XML body and can import a WSDL to create requests, which works for plain SOAP. Signed or encrypted messages and WSDL-driven generation of negative cases need extra scripting or a dedicated SOAP tool.

What tools are used for SOAP API testing?

Common choices are SoapUI Open Source and ReadyAPI for WSDL-first suites, Karate and REST Assured for code-based suites that mix SOAP and REST, Apache CXF or Python zeep to generate typed clients, and platforms such as Shift-Left API that generate SOAP tests from a WSDL and run them in CI.

Is there a free SOAP API for testing?

Several public demo services are often used for practice, such as simple calculator and temperature-conversion services, but they are run by third parties and can change or disappear. For anything you rely on, run a local mock from your own WSDL or use a sandbox your integration partner provides.


Sources and further reading

Key takeaways

  • SOAP testing is contract-first: the WSDL and its XML Schema define operations, types and the boundary values to test.
  • Assert on SOAP Faults (code and detail), not just HTTP 500, and always use namespaced XPath.
  • Cover functional, negative, boundary, XML-security (XXE, entity expansion, oversized payloads) and authorization cases.
  • Diff the WSDL and XSDs on every change; in regulated estates contract stability is the highest-value check.
  • Run SOAP tests in the same CI gate as REST, and decide deliberately where your WSDL is allowed to go.

Testing SOAP alongside REST and GraphQL? Get a free developer licence, or book a demo if you need self-hosted generation for a regulated estate.


Related: REST vs GraphQL vs gRPC Testing | How to Test GraphQL APIs | ReadyAPI vs Postman | On-Prem API Testing Buyer Checklist

Continue learning

Go deeper in the Learning Center

Hands-on lessons with runnable code against our live sandbox.

Ready to shift left with your API testing?

Import your OpenAPI spec and get a runnable test suite, in our cloud or on your own infrastructure.