{"id":14608,"library":"graphql-server-test","title":"GraphQL Server Testing with SuperTest","description":"The `graphql-server-test` library provides utilities for performing constructive HTTP-level integration and end-to-end testing of GraphQL servers. Leveraging the popular `supertest` library, it enables developers to simulate actual HTTP requests against their GraphQL endpoint, ensuring that the entire server stack—including middleware, authentication, and database interactions—behaves as expected. Currently at version 2.12.6, this package is actively maintained and ships with TypeScript type definitions, facilitating type-safe test development. Its primary differentiator is its focus on black-box HTTP testing for GraphQL, making it suitable for any server implementation (e.g., Apollo Server, Express-GraphQL) by interacting with it as a standard HTTP service. This approach contrasts with unit testing individual resolvers, offering a more realistic assessment of the GraphQL API's functionality in production-like environments.","status":"active","version":"2.12.6","language":"javascript","source_language":"en","source_url":"https://github.com/constructive-io/constructive","tags":["javascript","testing","graphql","graphile","constructive","supertest","http","integration","e2e","typescript"],"install":[{"cmd":"npm install graphql-server-test","lang":"bash","label":"npm"},{"cmd":"yarn add graphql-server-test","lang":"bash","label":"yarn"},{"cmd":"pnpm add graphql-server-test","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Core dependency for making HTTP assertions against the GraphQL server.","package":"supertest","optional":false},{"reason":"Needed for parsing and executing GraphQL queries and understanding schema definitions within tests.","package":"graphql","optional":false}],"imports":[{"note":"The library primarily uses named exports and is designed for ESM contexts. While CJS might work via transpilation, direct `require` is discouraged for modern Node.js environments.","wrong":"const createTestClient = require('graphql-server-test');","symbol":"createTestClient","correct":"import { createTestClient } from 'graphql-server-test';"},{"note":"This is a TypeScript type definition for the client object returned by `createTestClient`. It should be imported using `import type` to avoid runtime bundle inclusion.","wrong":"import { GraphQLTestClient } from 'graphql-server-test';","symbol":"GraphQLTestClient","correct":"import type { GraphQLTestClient } from 'graphql-server-test';"},{"note":"A utility tag function to parse GraphQL query strings, similar to `graphql-tag` or `apollo-server`'s `gql`.","symbol":"gql","correct":"import { gql } from 'graphql-server-test';"}],"quickstart":{"code":"import request from 'supertest';\nimport { ApolloServer } from '@apollo/server';\nimport { expressMiddleware } from '@apollo/server/express4';\nimport { ApolloServerPluginDrainHttpServer } from '@apollo/server/plugin/drainHttpServer';\nimport express from 'express';\nimport http from 'http';\nimport { createTestClient, gql } from 'graphql-server-test';\n\ninterface MyContext { user?: { id: string, name: string }; }\n\nconst typeDefs = `#graphql\n  type User {\n    id: ID!\n    name: String!\n  }\n\n  type Query {\n    hello: String!\n    me: User\n  }\n\n  type Mutation {\n    createUser(name: String!): User!\n  }\n`;\n\nconst users: { id: string, name: string }[] = [];\nlet nextId = 1;\n\nconst resolvers = {\n  Query: {\n    hello: () => 'world',\n    me: (_: any, __: any, context: MyContext) => context.user,\n  },\n  Mutation: {\n    createUser: (_: any, { name }: { name: string }) => {\n      const newUser = { id: String(nextId++), name };\n      users.push(newUser);\n      return newUser;\n    },\n  },\n};\n\nasync function startApolloServer() {\n  const app = express();\n  const httpServer = http.createServer(app);\n  const server = new ApolloServer<MyContext>({\n    typeDefs,\n    resolvers,\n    plugins: [ApolloServerPluginDrainHttpServer({ httpServer })],\n  });\n\n  await server.start();\n\n  app.use('/graphql', express.json(), expressMiddleware(server, {\n    context: async ({ req }) => {\n      const token = req.headers.authorization || '';\n      // Mock user for testing purposes\n      if (token === 'Bearer testuser') {\n        return { user: { id: '123', name: 'Test User' } };\n      }\n      return {};\n    },\n  }));\n\n  return app;\n}\n\ndescribe('GraphQL Server Integration Tests', () => {\n  let app: express.Application;\n  let client: ReturnType<typeof createTestClient>;\n\n  beforeAll(async () => {\n    app = await startApolloServer();\n    client = createTestClient(request(app));\n  });\n\n  it('should return \"world\" for the hello query', async () => {\n    const response = await client.query(gql`query { hello }`);\n    expect(response.status).toBe(200);\n    expect(response.body.data.hello).toBe('world');\n  });\n\n  it('should return the authenticated user', async () => {\n    const response = await client.query(\n      gql`query { me { id name } }`,\n      { headers: { Authorization: 'Bearer testuser' } }\n    );\n    expect(response.status).toBe(200);\n    expect(response.body.data.me).toEqual({ id: '123', name: 'Test User' });\n  });\n\n  it('should create a new user via mutation', async () => {\n    const response = await client.mutate(\n      gql`mutation CreateUser($name: String!) { createUser(name: $name) { id name } }`,\n      { variables: { name: 'New User' } }\n    );\n    expect(response.status).toBe(200);\n    expect(response.body.data.createUser).toHaveProperty('id');\n    expect(response.body.data.createUser.name).toBe('New User');\n  });\n});","lang":"typescript","description":"This quickstart demonstrates how to set up an Apollo Server with Express and use `graphql-server-test` to perform integration tests for queries and mutations, including context passing."},"warnings":[{"fix":"Consult the changelogs of `supertest`, your GraphQL server library (e.g., Apollo Server), and `graphql-server-test` for specific migration steps. Typically involves updating how the server is instantiated or middleware is applied.","message":"Major version updates (e.g., from v1 to v2) of `supertest` or underlying HTTP server frameworks (like Express or Apollo Server) can introduce breaking changes that might require updates to how the server application is configured or passed to `createTestClient`. Always review the changelogs of all dependent packages.","severity":"breaking","affected_versions":">=2.0.0"},{"fix":"Ensure `beforeAll`/`afterAll` or `beforeEach`/`afterEach` hooks are used correctly to manage the HTTP server's lifecycle. For `supertest`, pass the `express` app directly to `request()` without explicitly calling `listen()` in tests, as `supertest` handles this internally.","message":"Improper server lifecycle management in tests (e.g., not starting/stopping the HTTP server for each test suite or test file) can lead to 'address already in use' errors or resource leaks, especially with frameworks like Express or Apollo Server.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"When initializing your GraphQL server for testing, ensure that context functions or objects are configured to provide the necessary test-specific values, such as mocked users, data sources, or authentication tokens.","message":"GraphQL context in tests may not accurately reflect production if not explicitly set up. Authentication, authorization, and data source injection often depend on the context object, which needs to be properly mocked or constructed for tests.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Always use `await` when calling `client.query()` or `client.mutate()` and within `async` test functions. Ensure your test runner is configured to handle asynchronous tests (e.g., Jest's `done()` callback or returning a Promise).","message":"Asynchronous operations (queries, mutations) in GraphQL tests must be handled correctly with `async/await` to prevent flaky tests or incorrect assertions, as responses are Promises.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Ensure your `typeDefs` and `resolvers` are correctly defined and processed by your GraphQL server library (e.g., `makeExecutableSchema` from `@graphql-tools/schema` or `new ApolloServer({ typeDefs, resolvers })`). Double-check imports for `GraphQLSchema`.","cause":"The GraphQL server was initialized with an invalid schema object, or the schema was not correctly built before being passed to the server.","error":"TypeError: Schema must be an instance of GraphQLSchema."},{"fix":"Verify that your server application is correctly started before tests run (`beforeAll`) and shut down afterward (`afterAll`). If using `supertest` with an Express app, ensure you pass the app instance directly to `request(app)` rather than a URL.","cause":"The HTTP server was not running or properly listening on a port when `supertest` attempted to make a request, or the server instance was terminated prematurely.","error":"Error: socket hang up (or similar network error like ECONNREFUSED)"},{"fix":"Inspect the server logs for the full stack trace of the internal server error. Add error handling and logging to your GraphQL resolvers and middleware to surface more specific error messages in the test response.","cause":"A runtime error occurred within your GraphQL resolvers or server middleware that was not caught and formatted by the GraphQL server, resulting in a generic HTTP 500 status.","error":"HTTP Error: 500 Internal Server Error"},{"fix":"Compare the problematic query in your test with your GraphQL schema definition. Correct the query to match the available fields and types in your schema, paying attention to casing and nesting.","cause":"The GraphQL query sent in the test is requesting a field that does not exist on the specified type in your GraphQL schema.","error":"GraphQL error: Cannot query field 'X' on type 'Y'."}],"ecosystem":"npm"}