Mock Apollo Client for Unit Testing
Mock Apollo Client is a utility library designed to simplify unit testing of React components that interact with GraphQL APIs via `@apollo/client`. The current stable version is 2.x, which is compatible with `@apollo/client` v4.x. Previous major versions (1.x for Apollo Client v3, and 0.x for Apollo Client v2) exist for backward compatibility. The library helps address limitations found in Apollo Client's built-in `MockedProvider`, such as the inability to assert query/mutation variables, track call counts, dynamically change results after initialization, or easily control loading states. It offers a standalone, framework-agnostic mocking solution that provides granular control over GraphQL operations within tests, making it a powerful alternative for scenarios requiring more advanced testing capabilities than `MockedProvider` offers. Release cadence is tied to major `@apollo/client` updates.
Common errors
-
TypeError: Cannot read properties of undefined (reading 'query')
cause Often occurs when an older version of `mock-apollo-client` is used with a newer `@apollo/client` or vice-versa, leading to incompatible client interfaces.fixVerify that your `mock-apollo-client` and `@apollo/client` versions are compatible. For `@apollo/client@4.x`, use `mock-apollo-client@2.x`. For `@apollo/client@3.x`, use `mock-apollo-client@1.x`. -
ReferenceError: require is not defined in ES module scope
cause Attempting to use CommonJS `require()` syntax in an ESM project, or when the library is specifically published as ESM-only.fixUse ES module `import` syntax: `import { createMockClient } from 'mock-apollo-client';`. -
Error: GraphQL query was not found in the mock client's request handlers.
cause A GraphQL query was executed by the component under test, but no `setRequestHandler` was defined for that specific query in the `mock-apollo-client` instance.fixEnsure that `mockClient.setRequestHandler()` is called for every `gql` document (query or mutation) that your component is expected to execute during the test, before rendering the component.
Warnings
- breaking Major versions of `mock-apollo-client` are tightly coupled to major versions of `@apollo/client`. Using an incompatible version combination will lead to runtime errors or unexpected behavior.
- gotcha When using `setRequestHandler`, remember that the handler function is called with the variables provided to the GraphQL operation. This is your opportunity to assert variable values or dynamically change mock data based on inputs.
- gotcha `mock-apollo-client` is designed to complement, not entirely replace, `@apollo/client/testing`'s `MockedProvider`. For very simple, static mock scenarios, `MockedProvider` might be sufficient. `mock-apollo-client` shines in tests requiring dynamic responses, assertion of call variables/counts, or controlling loading states.
Install
-
npm install mock-apollo-client -
yarn add mock-apollo-client -
pnpm add mock-apollo-client
Imports
- createMockClient
const { createMockClient } = require('mock-apollo-client');import { createMockClient } from 'mock-apollo-client'; - createMockClient (type)
import type { ApolloClient } from '@apollo/client'; import { createMockClient } from 'mock-apollo-client'; - setRequestHandler
mockClient.setRequestHandler(GET_DOG_QUERY, () => { /* ... */ });
Quickstart
import '@testing-library/jest-dom';
import { ApolloProvider, gql } from '@apollo/client/react';
import { render, screen } from '@testing-library/react';
import { createMockClient } from 'mock-apollo-client';
// Imagine this is in dog.jsx
export const GET_DOG_QUERY = gql`
query getDog($name: String) {
dog(name: $name) {
id
name
breed
}
}
`;
// Imagine this is in dog.jsx
import { useQuery } from '@apollo/client/react';
export const Dog = ({ name }) => {
const { loading, error, data } = useQuery(GET_DOG_QUERY, {
variables: { name },
});
if (loading) return <p>Loading...</p>;
if (error) return <p>{error.message}</p>;
return (
<p>
{data.dog.name} is a {data.dog.breed}
</p>
);
};
describe('Dog component', () => {
it('renders the dog name and breed', async () => {
const mockClient = createMockClient();
mockClient.setRequestHandler(GET_DOG_QUERY, (variables) => {
// Assert variables if needed
expect(variables.name).toBe('Rufus');
return Promise.resolve({
data: { dog: { id: 1, name: 'Rufus', breed: 'Poodle' } },
});
});
render(
<ApolloProvider client={mockClient}>
<Dog name="Rufus" />
</ApolloProvider>,
);
expect(await screen.findByText('Rufus is a Poodle')).toBeInTheDocument();
});
});