REST vs SOAP vs GraphQL: Differences Every Tester Should Know

REST vs SOAP vs GraphQL: Differences Every Tester Should Know

“What is the difference between REST and SOAP?” has been asked in almost every API testing interview for over a decade, and GraphQL is now added to it. In this lesson you will see one real requirement, “get the balance and last two transactions of a bank customer”, built three ways, so the differences become obvious instead of memorised. Then you will learn how your test cases change for each style.

Quick answerREST is an architectural style that uses many resource URLs, HTTP methods and usually JSON. SOAP is a strict XML protocol with a WSDL contract, one endpoint per service and built-in WS-Security. GraphQL is a query language with a single endpoint where the client asks for exactly the fields it needs. REST suits most web and mobile apps, SOAP suits enterprise systems that need strict contracts and transactions (banking, insurance), and GraphQL suits apps with complex, changing data needs.
Advertisement

One Requirement, Three APIs

The mobile banking app needs: customer name, account balance and the last 2 transactions. Let’s see how each API style delivers it.

REST: several resource URLs

GET /v1/customers/42
GET /v1/accounts/ACC-4521
GET /v1/accounts/ACC-4521/transactions?limit=2
{ "data": { "id": "ACC-4521", "type": "savings", "balance": 18400.50,
            "currency": "INR", "branch": "Pune Camp", "ifsc": "SQAT0000123",
            "opened_on": "2019-06-11", "nominee": "...", "...": "many more fields" } }

Three round trips, and the account call returns many fields the screen never shows (over-fetching). Getting both pieces of data with one call isn’t possible (under-fetching), unless the team builds a custom endpoint.

SOAP: one operation, XML envelope

POST /CoreBankingService HTTP/1.1
Content-Type: text/xml; charset=utf-8
SOAPAction: "GetAccountSummary"

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
                  xmlns:cb="http://bank.example.com/core">
  <soapenv:Header><wsse:Security>...signed token...</wsse:Security></soapenv:Header>
  <soapenv:Body>
    <cb:GetAccountSummary>
      <cb:CustomerId>42</cb:CustomerId>
      <cb:TxnCount>2</cb:TxnCount>
    </cb:GetAccountSummary>
  </soapenv:Body>
</soapenv:Envelope>

Always POST, always XML, operation defined in the WSDL. Verbose, but every field, type and error is strictly defined.

GraphQL: one query, exact fields

POST /graphql
{
  customer(id: 42) {
    name
    account { balance currency }
    transactions(last: 2) { date amount description }
  }
}

One request, and the response contains exactly those fields and nothing else.

Advertisement

REST vs SOAP vs GraphQL: Comparison Table

FeatureRESTSOAPGraphQL
What it isArchitectural styleProtocol (W3C standard)Query language + runtime
Data formatJSON mostly (also XML, text)XML onlyJSON
EndpointsMany (one per resource)One per service, many operationsUsually one (/graphql)
HTTP methodsGET, POST, PUT, PATCH, DELETEMostly POSTMostly POST (GET for queries possible)
ContractOpenAPI / Swagger (optional)WSDL + XSD (mandatory)Schema (SDL), strongly typed
Error reportingHTTP status codes + error bodySOAP Fault element (often HTTP 500)errors array, often with HTTP 200
CachingEasy (HTTP caching, ETag)HardHard (single POST endpoint), needs client caching
SecurityHTTPS + OAuth 2.0/JWTWS-Security (signing, encryption) + HTTPSHTTPS + OAuth/JWT, plus query depth limits
Payload sizeMediumLarge (XML envelope)Small (only requested fields)
Learning curveEasySteeperMedium
Typical usersMost web and mobile appsBanks, insurance, telecom, governmentGitHub, Shopify, Meta, data-rich dashboards
Testing toolsPostman, Playwright, REST AssuredSoapUI, ReadyAPI, PostmanPostman, Playwright, Insomnia

REST in Detail (with a Live Example)

REST follows six constraints: client-server, stateless, cacheable, uniform interface, layered system and (optional) code on demand. For testers the important ideas are: resources as URLs, methods as actions and status codes as results.

Request the same user in JSON (default) and, with content negotiation, in XML. REST lets one resource have several representations:

GEThttps://sqatools.in/wp-json/sqa-api/v1/users/1
curl -i \
  -H "Accept: application/xml" \
  "https://sqatools.in/wp-json/sqa-api/v1/users/1"

Change the Accept header to text/csv and the API replies 406 Not Acceptable, a great negative test.

Advertisement

SOAP in Detail

A SOAP message has four parts:

  • Envelope (mandatory): root element that marks the XML as a SOAP message.
  • Header (optional): security tokens, transaction ids, routing.
  • Body (mandatory): the operation and its parameters, or the response.
  • Fault (inside Body, on errors): faultcode, faultstring and detail.
<soap:Body>
  <soap:Fault>
    <faultcode>soap:Client</faultcode>
    <faultstring>Invalid account number</faultstring>
    <detail><cb:ErrorCode>ACC-404</cb:ErrorCode></detail>
  </soap:Fault>
</soap:Body>
Real-life example: insurance policy issue An insurance company’s agent portal calls a SOAP IssuePolicy operation. WS-Security signs the message, so it cannot be changed in transit. WS-AtomicTransaction makes sure payment capture and policy creation both succeed or both roll back. This is exactly why regulated industries stay on SOAP.

You will test SOAP hands-on in the SoapUI lessons of Module 4.

GraphQL in Detail

GraphQL has three operation types:

  • Query: read data.
  • Mutation: create, update or delete data.
  • Subscription: real-time updates, usually over WebSocket.
// Partial success: HTTP 200, but one field failed
{
  "data": { "customer": { "name": "Asha Verma", "transactions": null } },
  "errors": [
    { "message": "Not authorised to view transactions", "path": ["customer", "transactions"] }
  ]
}

This is the biggest trap for testers coming from REST: a 200 does not mean success. Always assert that errors is absent (or contains what you expect).

Advertisement

How Test Cases Differ for Each Style

Test areaRESTSOAPGraphQL
PositiveEach method on each resourceEach WSDL operationEach query and mutation, different field selections
Validation400/422 with field errorsSOAP Fault, XSD validationErrors array, type errors from schema
ContractJSON Schema / OpenAPI diffWSDL/XSD complianceSchema diff, deprecated fields
SecurityAuth, BOLA, rate limitWS-Security, XML injection, XXEField-level auth, depth/complexity limits, introspection off
PerformancePer endpointPer operation, payload sizeExpensive nested queries, N+1 problem
AssertionsJSON path on bodyXPath / XQueryJSON path on data and errors

Playwright Example: Testing REST and GraphQL the Same Way

Playwright’s request fixture can call any HTTP API, so the same framework covers REST, GraphQL and even SOAP (as a POST with an XML body).

import { test, expect } from '@playwright/test';

test('REST: content negotiation returns XML', async ({ request }) => {
  const res = await request.get('https://sqatools.in/wp-json/sqa-api/v1/users/1', {
    headers: { Accept: 'application/xml' },
  });
  expect(res.status()).toBe(200);
  expect(res.headers()['content-type']).toContain('application/xml');
  expect(await res.text()).toContain('<name>Asha Verma</name>');
});

test('GraphQL: assert data AND errors', async ({ request }) => {
  const res = await request.post('https://example.com/graphql', {
    data: { query: '{ user(id: 1) { name email } }' },
  });
  expect(res.status()).toBe(200);
  const body = await res.json();
  expect(body.errors).toBeUndefined();          // the important GraphQL check
  expect(body.data.user.name).toBe('Asha Verma');
});

test('SOAP: post an XML envelope', async ({ request }) => {
  const envelope = `<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>`;
  const res = await request.post('http://www.dneonline.com/calculator.asmx', {
    headers: { 'Content-Type': 'text/xml; charset=utf-8', SOAPAction: '"http://tempuri.org/Add"' },
    data: envelope,
  });
  expect(res.status()).toBe(200);
  expect(await res.text()).toContain('<AddResult>12</AddResult>');
});

The GraphQL URL above is a placeholder; replace it with your project’s endpoint. The SOAP calculator is a free public demo service.

Advertisement

When to Choose Which (Decision Guide)

  • Choose REST for public APIs, CRUD-style apps, mobile backends and anything that benefits from HTTP caching.
  • Choose SOAP when a partner or regulator requires it, or you need WS-Security signing and distributed transactions.
  • Choose GraphQL when many different clients (web, Android, iOS, smart TV) need different shapes of the same data and you want to avoid many custom endpoints.
Interview tip Don’t say “REST is better than SOAP”. Say “they solve different problems”, give one real example of each from your project or industry, and mention one testing difference (status codes vs SOAP Faults, or the GraphQL 200-with-errors trap). That answer stands out.
Advertisement

Common Myths

  • “REST always uses JSON.” No, REST can return XML, CSV or anything; the practice API returns XML when asked.
  • “SOAP is dead.” No, it still runs core systems in banking, insurance, airlines and government.
  • “GraphQL replaces REST.” Most companies run both; GraphQL often sits in front of REST services.
  • “SOAP only works over HTTP.” It can also use SMTP, JMS and other transports.
Advertisement

Interview Questions: REST vs SOAP vs GraphQL

What is the difference between REST and SOAP?

REST is an architectural style using resource URLs, HTTP methods, status codes and usually JSON; it is lightweight and cacheable. SOAP is an XML-based protocol with a mandatory WSDL contract, an envelope structure, SOAP Faults for errors and WS-Security for message-level security. REST suits web and mobile apps; SOAP suits enterprise systems needing strict contracts and transactions.

Can REST use XML?

Yes. REST is format-independent. The client asks for a format with the Accept header and the server answers with Content-Type. JSON is just the most common choice.

What is a SOAP Fault?

The standard error element inside the SOAP Body, containing faultcode, faultstring and optional detail. It is usually returned with HTTP status 500. Testers assert on the fault code and message using XPath.

What are over-fetching and under-fetching?

Over-fetching is getting more fields than you need; under-fetching is needing several calls to get all the data for one screen. GraphQL solves both by letting the client request exactly the fields it needs in one query.

Why is GraphQL harder to cache than REST?

REST GET requests have unique URLs that browsers, CDNs and proxies can cache. GraphQL usually sends every query as a POST to one URL, so HTTP caching doesn’t work out of the box; clients use their own normalised caches or persisted queries.

What are the three operation types in GraphQL?

Query to read data, mutation to change data and subscription to receive real-time updates.

How do you validate a SOAP response?

Check the HTTP status, validate it against the XSD in the WSDL, assert values with XPath, check that no SOAP Fault is present for positive cases, and verify the fault code and message for negative cases. SoapUI provides all of these assertions.

Which is more secure, REST or SOAP?

Neither is automatically more secure. SOAP has built-in WS-Security for message-level signing and encryption. REST relies on HTTPS plus OAuth 2.0 or JWT, which is secure when implemented correctly. Security depends on the implementation and must be tested.

What is the main testing trap in GraphQL?

Errors often come back with HTTP 200 inside an errors array, and partial data can be returned. Tests that only check the status code will pass while the feature is broken.

Which tool would you use to test SOAP services and why?

SoapUI (or ReadyAPI), because it imports the WSDL, generates request templates for every operation, and provides XPath, XSD and SOAP Fault assertions plus data-driven testing. Postman can also send SOAP requests but with less WSDL support.

Advertisement
View the full API testing syllabus