How to Test Apollo Client in React
Testing React components that integrate with Apollo Client is
essential for ensuring your UI correctly handles GraphQL queries,
mutations, loading states, and error conditions. This article provides a
direct, step-by-step guide on how to use MockedProvider
from @apollo/client/testing alongside React Testing Library
to simulate GraphQL network traffic and verify your component behavior
without a live backend.
Setting Up the MockedProvider
The @apollo/client/testing package provides a
MockedProvider component. This utility acts as a
replacement for the standard ApolloProvider in your test
files. Instead of sending actual network requests to a GraphQL endpoint,
MockedProvider intercepts queries and mutations and returns
pre-configured mock data.
To test a component, wrap it inside MockedProvider and
pass an array of mock objects to its mocks prop.
Defining Mock Data
Each mock object in your mocks array must precisely
match the GraphQL request your component makes. A mock contains two main
properties: * request: Specifies the exact
query or mutation and its associated variables. *
result: Specifies the mock data or error
payload that should be returned.
Here is an example of a mock configuration:
import { GET_USER } from './UserComponent';
const mocks = [
{
request: {
query: GET_USER,
variables: { id: '1' },
},
result: {
data: {
user: { id: '1', name: 'John Doe', email: 'john@example.com' },
},
},
},
];Writing the Test Case
When writing your tests with React Testing Library, you should test
the different states of your component: loading, success, and error.
Because GraphQL requests are asynchronous, you must use asynchronous
utilities like findByText or waitFor to assert
the final rendered state.
import React from 'react';
import { render, screen } from '@testing-library/react';
import { MockedProvider } from '@apollo/client/testing';
import { UserComponent, GET_USER } from './UserComponent';
const mocks = [
{
request: {
query: GET_USER,
variables: { id: '1' },
},
result: {
data: {
user: { id: '1', name: 'John Doe', email: 'john@example.com' },
},
},
},
];
test('renders loading and then success state', async () => {
render(
<MockedProvider mocks={mocks} addTypename={false}>
<UserComponent id="1" />
</MockedProvider>
);
// 1. Verify loading state is displayed initially
expect(screen.getByText(/loading/i)).toBeInTheDocument();
// 2. Wait for the mock response to resolve and verify UI changes
const userName = await screen.findByText('John Doe');
expect(userName).toBeInTheDocument();
expect(screen.queryByText(/loading/i)).not.toBeInTheDocument();
});Note: Passing addTypename={false} to the
MockedProvider prevents Apollo Client from automatically
adding __typename fields to your queries, which makes
writing mock objects simpler.
Testing Error States
To test how your component behaves when a GraphQL operation fails, you can simulate either a network error or a GraphQL execution error inside your mock definition.
Simulating a GraphQL Error
You can return an errors array in the mock
result object to simulate backend validation or execution
failures.
const errorMock = [
{
request: {
query: GET_USER,
variables: { id: '1' },
},
result: {
errors: [new Error('GraphQL Error Occurred')],
},
},
];Simulating a Network Error
To simulate a complete network or connection failure, provide an
error property directly on the mock object instead of a
result property.
const networkErrorMock = [
{
request: {
query: GET_USER,
variables: { id: '1' },
},
error: new Error('A network error occurred'),
},
];By verifying these various states with MockedProvider,
you ensure your React application remains resilient and handles data
fetching predictably across all scenarios.