How to Mock Apollo Client in React

Testing React components that integrate with GraphQL requires a reliable way to simulate network requests without hitting a live server. This article explains how to mock Apollo Client in React using the official MockedProvider utility. You will learn how to define mock requests, inject them into your components during testing, and handle asynchronous loading and success states.

Using MockedProvider

The @apollo/client/testing package provides MockedProvider, a component that mocks the behavior of ApolloProvider. Instead of sending network requests to a GraphQL endpoint, MockedProvider intercepts queries and mutations and returns predefined mock data that you specify.

1. Create the Mock Data

To mock a query, you need to define an array of mock objects. Each mock object contains a request property (specifying the query and variables to match) and a result property (specifying the data to return).

import { gql } from '@apollo/client';

export const GET_USER_QUERY = gql`
  query GetUser($id: ID!) {
    user(id: $id) {
      id
      name
      email
    }
  }
`;

export const mocks = [
  {
    request: {
      query: GET_USER_QUERY,
      variables: { id: '1' },
    },
    result: {
      data: {
        user: {
          id: '1',
          name: 'John Doe',
          email: 'john@example.com',
        },
      },
    },
  },
];

2. Write the Component Test

When rendering your component in a test environment (such as React Testing Library), wrap the component with MockedProvider and pass the mock array to the mocks prop.

import React from 'react';
import { render, screen } from '@testing-library/react';
import { MockedProvider } from '@apollo/client/testing';
import { UserComponent } from './UserComponent';
import { GET_USER_QUERY, mocks } from './mocks';

test('renders user data successfully', async () => {
  render(
    <MockedProvider mocks={mocks} addTypename={false}>
      <UserComponent id="1" />
    </MockedProvider>
  );

  // Verify the loading state first
  expect(screen.getByText(/loading.../i)).toBeInTheDocument();

  // Wait for the mock data to resolve and render
  const nameElement = await screen.findByText('John Doe');
  expect(nameElement).toBeInTheDocument();
  expect(screen.getByText('john@example.com')).toBeInTheDocument();
});

3. Key Considerations

4. Mocking Mutations

Mocking mutations follows the exact same pattern. You specify the mutation query, the input variables, and the expected result inside the mock array.

const UPDATE_USER_MUTATION = gql`
  mutation UpdateUser($id: ID!, $name: String!) {
    updateUser(id: $id, name: $name) {
      id
      name
    }
  }
`;

const mutationMock = {
  request: {
    query: UPDATE_USER_MUTATION,
    variables: { id: '1', name: 'Jane Doe' },
  },
  result: {
    data: {
      updateUser: {
        id: '1',
        name: 'Jane Doe',
        __typename: 'User',
      },
    },
  },
};