GraphQL API testing checks an API where the client asks for exactly the fields it wants in a single query, sent to one endpoint. The ideas you know from REST testing still apply, but three things change how you test: everything goes through one URL, errors usually come back with HTTP 200, and the client controls the shape of the response. This guide covers what to test and how, with Postman and REST Assured examples.

GraphQL vs REST in One Minute

RESTGraphQL
EndpointsMany: /users, /users/7/ordersUsually one: /graphql
Who decides the response fieldsThe serverThe client, field by field
Reading dataGETA query, usually sent with POST
Changing dataPOST / PUT / PATCH / DELETEA mutation
ErrorsHTTP status codes (400, 404, 500)Often HTTP 200 with an errors array
ContractOpenAPI spec (optional)A typed schema (always present)
Advertisement

Anatomy of a GraphQL Request

A GraphQL request is an HTTP POST with a JSON body containing the query text and, ideally, separate variables:

POST /graphql HTTP/1.1
Content-Type: application/json
Authorization: Bearer eyJhbGciOi...

{
  "query": "query GetUser($id: ID!) { user(id: $id) { id name email orders(first: 2) { id total } } }",
  "variables": { "id": "7" }
}

The response mirrors the query, with only the requested fields:

{
  "data": {
    "user": {
      "id": "7",
      "name": "Asha",
      "email": "asha@example.com",
      "orders": [ { "id": "1042", "total": 499 }, { "id": "1043", "total": 1299 } ]
    }
  }
}

A mutation looks the same but starts with mutation, for example mutation { createUser(input: {name: "Ravi"}) { id } }.

What to Test in a GraphQL API

1. The schema

The schema is the contract. Check that types, required fields (marked !) and enum values match the requirements, and watch for breaking changes between releases: a removed field or a field that became required breaks existing clients. Tools such as GraphQL Inspector can compare two schema versions automatically.

2. Queries and field selection

  • Ask for one field, many fields and nested objects; the response must contain exactly what was asked, no more.
  • Check nullable fields return null (not an error) when data is missing.
  • Test arguments: valid IDs, unknown IDs, filters, sorting and pagination (first/after cursors or limit/offset).

3. Mutations

Verify the change actually happened (query it back or check the database), that the mutation returns the updated object, and that invalid input is rejected with a clear message. Test that running the same mutation twice behaves as designed, for example no duplicate orders.

4. Errors and the 200 trap

This is where most REST habits fail. A GraphQL server usually returns HTTP 200 even when the query fails, with details in an errors array:

{
  "data": { "user": null },
  "errors": [ { "message": "User not found", "path": ["user"], "extensions": { "code": "NOT_FOUND" } } ]
}

So never assert only on the status code. Check that errors is absent for valid requests, and for invalid ones assert on the error code and message. Also note that a response can be partly successful: some fields in data and an error for another field.

5. Authorization at field level

Because one query can reach many objects, check permissions on every type and field, not just the endpoint. A normal user querying another user's orders or an admin-only field like salary must get an error or null, never the data.

6. Abuse and performance

  • Deeply nested queries (user → orders → user → orders …) can overload the server; there should be a depth or complexity limit.
  • Large page sizes such as first: 100000 should be capped.
  • N+1 queries: a list of 50 users with their orders shouldn't trigger 51 database calls; watch response time as the list grows.
  • Introspection is useful in test environments but is often disabled in production; check what your team decided.

Testing GraphQL in Postman

In a Postman request, set the method to POST, choose Body → GraphQL, and write the query and variables in the two panels. Postman can fetch the schema for autocompletion. Tests are written the same way as for REST:

const body = pm.response.json();
pm.test("no GraphQL errors", () => pm.expect(body.errors).to.be.undefined);
pm.test("returns the requested user", () => {
  pm.expect(body.data.user.id).to.eql("7");
  pm.expect(body.data.user).to.have.all.keys("id", "name", "email", "orders");
});

Testing GraphQL with REST Assured

REST Assured has no special GraphQL support and doesn't need it: send the query and variables as a JSON body.

String query = "query GetUser($id: ID!) { user(id: $id) { id name email } }";
Map<String, Object> payload = Map.of("query", query, "variables", Map.of("id", "7"));

given()
    .baseUri("https://api.example.com")
    .contentType(ContentType.JSON)
    .auth().oauth2(token)
    .body(payload)
.when()
    .post("/graphql")
.then()
    .statusCode(200)
    .body("errors", nullValue())
    .body("data.user.id", equalTo("7"))
    .body("data.user.email", containsString("@"));

Keep queries in .graphql files under src/test/resources and load them in tests, so they are readable and reusable.

GraphQL Testing Checklist

AreaCheck
SchemaTypes, required fields and enums match; no unplanned breaking changes
QueriesExact field selection, nested objects, nulls, arguments, pagination
MutationsData really changes, invalid input rejected, repeat calls handled
Errorserrors array checked, not just HTTP 200; partial results handled
SecurityField-level authorization, depth/complexity limits, page-size caps
PerformanceResponse time with large lists, no N+1 behaviour

FAQs

Is GraphQL testing different from REST API testing?

The goals are the same, but GraphQL uses one endpoint, lets the client pick fields, and usually returns HTTP 200 even for errors. Tests must check the errors array, field selection and field-level permissions.

Can Postman test GraphQL APIs?

Yes. Choose Body → GraphQL in a POST request to write queries and variables, fetch the schema for autocompletion, and write tests in the Tests tab as usual.

Why does a failed GraphQL request return status 200?

Because the HTTP request itself succeeded; the failure is reported in the errors array of the JSON response. Some servers do return 4xx for malformed requests, but you should always assert on errors.

What is introspection in GraphQL?

A built-in query that returns the API's schema: its types, fields and arguments. Tools use it for autocompletion and documentation; many teams disable it in production.