Skip to main content

GraphQL Support

A graphql block lets a test send a GraphQL query or mutation without hand-building the request envelope. Declare the query and variables; ConfIT composes the { query, variables, operationName } JSON body, sets the HTTP method, and sets Content-Type — the same request pipeline (matchers, extract, {{inject}}, mocking) applies afterward exactly as it does for any other test.

graphql is sugar over the existing body / method / headers fields — it is resolved once, at load time, into the same request a hand-written test would produce. It works in both api.request and mock.interactions[].request.


Structure

"request": {
"path": "/graphql",
"graphql": {
"query": "query { userById(id: 1) { id name } }"
}
}
FieldRequiredDescription
queryone of query / queryFromFileInline query or mutation text
queryFromFileone of query / queryFromFileLoad query text from a file in RequestBodyFolder
variablesInline JSON object passed as GraphQL variables
operationNameNamed operation to run, when the document defines more than one

Exactly one of query / queryFromFile must be set — a test with neither fails to load with Test case's 'graphql' block must set either 'query' or 'queryFromFile'.


What gets composed

  • request.body becomes { "query": "...", "variables": {...}, "operationName": "..." }. The variables and operationName keys are included only when set — an inline query with no variables produces a body with just query.
  • request.method defaults to POST only if not already set. An explicit method in the DSL is never overridden.
  • Content-Type: application/json is added only if no Content-Type header is already present (checked case-insensitively) — set your own to override it.

queryFromFile

Loads query text from a file in the same RequestBodyFolder used by bodyFromFile — see Test File Format. If both query and queryFromFile are set, queryFromFile wins silently, mirroring bodyFromFile / body precedence.

GetUserById_QueryFromFile:
api:
request:
method: POST
path: /graphql
graphql:
queryFromFile: user-by-id.graphql
variables:
id: "{{graphqlUserId}}"

Request/user-by-id.graphql:

query GetUserById($id: Int!) {
userById(id: $id) {
id
name
email
age
}
}

📄 Live example: User.ComponentTests/TestCase/05-graphql.yamlGetUserById_QueryFromFile


Mutations and extract

A GraphQL mutation is just another response body — extract and matcher.semantic apply to data.<field> the same way they apply anywhere else.

CreateUserMutation:
api:
request:
method: POST
path: /graphql
graphql:
query: |
mutation CreateUser($input: CreateUserCommandInput!) {
createUser(input: $input) {
id
}
}
variables:
input:
name: graphql-user
email: graphql-user@test.com
age: 25
response:
statusCode: 200
body:
data:
createUser: {}
extract:
graphqlUserId: $.body.data.createUser.id
matcher:
semantic:
data__createUser__id: greaterThan(0)

📄 Live example: User.ComponentTests/TestCase/05-graphql.yamlCreateUserMutation


Inline query with {{inject}}

Since query is plain text, {{varName}} injection works inside it exactly as it does in path or body.

GetUserById_InlineQuery:
depends:
- CreateUserMutation
api:
request:
method: POST
path: /graphql
graphql:
query: |
query {
userById(id: {{graphqlUserId}}) {
id
name
email
age
}
}

📄 Live example: User.ComponentTests/TestCase/05-graphql.yamlGetUserById_InlineQuery


Matching GraphQL errors

A GraphQL response can return 200 OK with a populated errors array. Since errors is a normal JSON array, the standard matchers apply — including the array-wildcard * segment for asserting on every entry regardless of count. See Matchers and Patterns — array-wildcard segments.

GetUserById_MultipleErrors:
api:
request:
method: POST
path: /graphql
graphql:
query: |
query {
a: userById(id: 99998) { id }
b: userById(id: 99999) { id }
}
response:
statusCode: 200
body:
data:
a: null
b: null
errors:
- message: "User doesn't exist with Id : 99998"
- message: "User doesn't exist with Id : 99999"
matcher:
ignore:
- errors__*__extensions
- errors__*__path

📄 Live example: User.ComponentTests/TestCase/05-graphql.yamlGetUserById_MultipleErrors


Mocking a GraphQL dependency

mock.interactions[].request accepts graphql the same way api.request does — useful when the service under test itself calls a downstream GraphQL API. WireMock still matches on the composed body, so overlapping stubs on the same path are disambiguated by query/variables content exactly as they are for REST mocks — see Mock Interactions.


Quick reference

FieldWhereRequiredDescription
request.graphql.queryapi / mock.interactions[]one of query / queryFromFileInline query or mutation text
request.graphql.queryFromFileapi / mock.interactions[]one of query / queryFromFileLoad query text from RequestBodyFolder
request.graphql.variablesapi / mock.interactions[]noInline JSON object of GraphQL variables
request.graphql.operationNameapi / mock.interactions[]noNamed operation to run