GraphQL Server Testing with SuperTest

2.12.6 · active · verified Sun Apr 19

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.

Common errors

Warnings

Install

Imports

Quickstart

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.

import request from 'supertest';
import { ApolloServer } from '@apollo/server';
import { expressMiddleware } from '@apollo/server/express4';
import { ApolloServerPluginDrainHttpServer } from '@apollo/server/plugin/drainHttpServer';
import express from 'express';
import http from 'http';
import { createTestClient, gql } from 'graphql-server-test';

interface MyContext { user?: { id: string, name: string }; }

const typeDefs = `#graphql
  type User {
    id: ID!
    name: String!
  }

  type Query {
    hello: String!
    me: User
  }

  type Mutation {
    createUser(name: String!): User!
  }
`;

const users: { id: string, name: string }[] = [];
let nextId = 1;

const resolvers = {
  Query: {
    hello: () => 'world',
    me: (_: any, __: any, context: MyContext) => context.user,
  },
  Mutation: {
    createUser: (_: any, { name }: { name: string }) => {
      const newUser = { id: String(nextId++), name };
      users.push(newUser);
      return newUser;
    },
  },
};

async function startApolloServer() {
  const app = express();
  const httpServer = http.createServer(app);
  const server = new ApolloServer<MyContext>({
    typeDefs,
    resolvers,
    plugins: [ApolloServerPluginDrainHttpServer({ httpServer })],
  });

  await server.start();

  app.use('/graphql', express.json(), expressMiddleware(server, {
    context: async ({ req }) => {
      const token = req.headers.authorization || '';
      // Mock user for testing purposes
      if (token === 'Bearer testuser') {
        return { user: { id: '123', name: 'Test User' } };
      }
      return {};
    },
  }));

  return app;
}

describe('GraphQL Server Integration Tests', () => {
  let app: express.Application;
  let client: ReturnType<typeof createTestClient>;

  beforeAll(async () => {
    app = await startApolloServer();
    client = createTestClient(request(app));
  });

  it('should return "world" for the hello query', async () => {
    const response = await client.query(gql`query { hello }`);
    expect(response.status).toBe(200);
    expect(response.body.data.hello).toBe('world');
  });

  it('should return the authenticated user', async () => {
    const response = await client.query(
      gql`query { me { id name } }`,
      { headers: { Authorization: 'Bearer testuser' } }
    );
    expect(response.status).toBe(200);
    expect(response.body.data.me).toEqual({ id: '123', name: 'Test User' });
  });

  it('should create a new user via mutation', async () => {
    const response = await client.mutate(
      gql`mutation CreateUser($name: String!) { createUser(name: $name) { id name } }`,
      { variables: { name: 'New User' } }
    );
    expect(response.status).toBe(200);
    expect(response.body.data.createUser).toHaveProperty('id');
    expect(response.body.data.createUser.name).toBe('New User');
  });
});

view raw JSON →