API Testing

Testing GraphQL APIs: Queries, Mutations, and Variables

GraphQL testing has different conventions than REST — one endpoint, a query language, and variables instead of path parameters. Here's the actual workflow.

AlleForge TeamAugust 16, 20262 min read

GraphQL doesn't map onto the REST testing mental model directly — there's usually one endpoint, not dozens, and what you're sending is a query, not a method-and-path combination. This is the workflow that actually applies.

One endpoint, a query in the body

A GraphQL API typically exposes a single endpoint (often /graphql), and every request — read or write — is a POST with the query itself in the body:

query GetUser($id: ID!) {
  user(id: $id) {
    id
    name
    email
  }
}

The $id: ID! is a variable — sent separately from the query itself, not interpolated into the string:

{
  "id": "usr_492"
}

Queries vs. mutations

  • Query — read data. Equivalent in spirit to a REST GET.
  • Mutation — change data. Equivalent in spirit to POST/PUT/PATCH/DELETE, all expressed as one concept.

A mutation looks structurally the same as a query, just declared with mutation instead:

mutation UpdateUserEmail($id: ID!, $email: String!) {
  updateUser(id: $id, email: $email) {
    id
    email
  }
}

Authentication works the same way

GraphQL doesn't change how auth is sent — a bearer token still goes in the Authorization header, same as a REST request. If every query against this API needs the same token, inherited auth on the collection applies exactly the same way here as it does for REST.

Reading the response — including partial errors

A GraphQL response can contain both data and errors in the same 200 OK — a field that failed to resolve doesn't necessarily fail the whole request:

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

This is the detail that trips people up coming from REST: a 200 status here doesn't mean "everything succeeded" the way it usually does for a REST endpoint — check the errors array, not just the status code.

Schema introspection

Most GraphQL APIs support introspection — querying the schema itself to see what types, queries, and mutations exist, without needing separate documentation to discover them. If you're exploring an unfamiliar GraphQL API, this is usually the fastest way to see what's actually available before writing your first real query.

Where this doesn't help

Whether an API's introspection is enabled at all is up to that API — some disable it in production for their own reasons, in which case you're back to reading whatever schema documentation the API provides directly.

See this in AlleForge

Open API Testing