Apollo Server Integration Testing Utilities
raw JSON →This package provides essential utilities for conducting true integration tests on Apollo Server instances, especially when the server's `context` option depends on mocked HTTP `Request` or `Response` objects. Unlike the now-deprecated `apollo-server-testing` package, which often resulted in `req` being undefined in the context function, `apollo-server-integration-testing` automatically provides robust mock objects, enabling comprehensive testing of server logic, including middleware and resolvers that access `req` or `res`. The package's current stable version is 3.0.0, and while it doesn't have a fixed release cadence, it generally aims to support relevant versions of `graphql` (from 0.12.0 up to 15.0.0 as per its peer dependencies) to remain compatible with various Apollo Server setups. Its key differentiator is its ability to simulate a full HTTP request/response cycle, making it suitable for integration and end-to-end testing where `ApolloServer.executeOperation` (recommended for simpler unit tests) is insufficient.
Common errors
error Cannot read properties of undefined (reading 'req') / TypeError: Cannot read property 'req' of undefined ↓
apollo-server-integration-testing for tests that require req or res objects in the context, or manually mock the context argument when using ApolloServer.executeOperation if a full HTTP mock isn't needed. Alternatively, if using apollo-server-integration-testing, ensure extendMockRequest or setOptions provide the necessary req properties. error ApolloServer must be started before it can be used. Call `await server.start()` before `applyMiddleware()` or `listen()`. ↓
await apolloServer.start(); after creating your new ApolloServer(...) instance and before passing apolloServer to createTestClient. Warnings
gotcha When testing Apollo Server `context` functions that rely on `req` or `res` objects, using the official `apollo-server-testing` package (now deprecated in favor of `server.executeOperation`) will result in `req` being `undefined`. This package (`apollo-server-integration-testing`) is specifically designed to address this limitation by providing robust mock HTTP request/response objects. ↓
breaking Apollo Server v3 and later versions require calling `await server.start()` before the server can be used. Failing to do so will result in runtime errors. This applies when you are passing an `ApolloServer` instance to `createTestClient`. ↓
gotcha The `graphql` peer dependency for `apollo-server-integration-testing` has a wide range (`^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0`). However, the specific version of `graphql` required by your `Apollo Server` package (e.g., Apollo Server 3 requires `graphql` v15.3.0+, Apollo Server 4 requires `graphql` v16+) might be more restrictive. A mismatch can lead to unexpected behavior or conflicts. ↓
Install
npm install apollo-server-integration-testing yarn add apollo-server-integration-testing pnpm add apollo-server-integration-testing Imports
- createTestClient wrong
const { createTestClient } = require('apollo-server-integration-testing');correctimport { createTestClient } from 'apollo-server-integration-testing'; - TestClient
import type { TestClient } from 'apollo-server-integration-testing'; - setOptions
const { query, setOptions } = createTestClient({ apolloServer });
Quickstart
import { createTestClient } from 'apollo-server-integration-testing';
import { ApolloServer } from '@apollo/server';
import { buildSubgraphSchema } from '@apollo/subgraph';
import gql from 'graphql-tag';
const typeDefs = gql`
type User {
id: ID!
email: String
}
type Query {
currentUser: User
}
type Mutation {
updateUser(id: ID!, email: String!): User
}
`;
const resolvers = {
Query: {
currentUser: (_, __, { req }) => {
// Simulate context logic that depends on req
if (req?.headers?.authorization) {
return { id: '1', email: 'test@example.com' };
}
return null;
},
},
Mutation: {
updateUser: (_, { id, email }) => ({ id, email }),
},
};
async function createApolloServer() {
const server = new ApolloServer({
schema: buildSubgraphSchema({ typeDefs, resolvers }),
});
await server.start(); // Mandatory for Apollo Server v3+
return server;
}
describe('Apollo Server Integration Tests', () => {
let apolloServer;
let query;
let mutate;
let setOptions;
beforeAll(async () => {
apolloServer = await createApolloServer();
({ query, mutate, setOptions } = createTestClient({
apolloServer,
extendMockRequest: {
headers: { authorization: 'Bearer token' }
}
}));
});
afterAll(async () => {
await apolloServer.stop();
});
test('should fetch current user with mocked request headers', async () => {
const result = await query(`{ currentUser { id email } }`);
expect(result).toEqual({
data: {
currentUser: {
id: '1',
email: 'test@example.com'
}
}
});
});
test('should update user and allow subsequent request modification', async () => {
setOptions({
request: { headers: { authorization: 'Bearer another-token' } }
});
const UPDATE_USER_MUTATION = `
mutation UpdateUser($id: ID!, $email: String!) {
updateUser(id: $id, email: $email) {
id
email
}
}
`;
const mutationResult = await mutate(UPDATE_USER_MUTATION, {
variables: { id: '1', email: 'jane.doe@example.com' }
});
expect(mutationResult).toEqual({
data: {
updateUser: {
id: '1',
email: 'jane.doe@example.com'
}
}
});
});
});