How to Mock Axios in React

Testing React components that fetch data requires simulating API requests to prevent slow, flaky tests that rely on external servers. This article provides a straightforward guide on how to mock the Axios library in React using Jest and React Testing Library. We will cover the standard Jest mocking approach and how to use the popular axios-mock-adapter library.

Method 1: Mocking Axios with Jest (jest.mock)

The most common way to mock Axios in a React environment is by using Jest’s built-in mocking capabilities. This method intercepts imports of axios and replaces them with mock functions.

Step 1: Create the Component

Assume you have a component that fetches and displays a list of users:

import React, { useState, useEffect } from 'react';
import axios from 'axios';

export default function UserList() {
  const [users, setUsers] = useState([]);

  useEffect(() => {
    axios.get('https://jsonplaceholder.typicode.com/users')
      .then(response => setUsers(response.data))
      .catch(error => console.error(error));
  }, []);

  return (
    <ul>
      {users.map(user => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
}

Step 2: Write the Test with jest.mock

In your test file, use jest.mock('axios') to spy on and control the Axios behavior.

import React from 'react';
import { render, screen, waitFor } from '@testing-library/react';
import axios from 'axios';
import UserList from './UserList';

// Mock the axios module
jest.mock('axios');

test('fetches and displays users successfully', async () => {
  const mockUsers = [
    { id: 1, name: 'John Doe' },
    { id: 2, name: 'Jane Smith' },
  ];

  // Define the resolved value for the mocked axios.get method
  axios.get.mockResolvedValue({ data: mockUsers });

  render(<UserList />);

  // Wait for the mock data to render
  const user1 = await screen.findByText('John Doe');
  const user2 = await screen.findByText('Jane Smith');

  expect(user1).toBeInTheDocument();
  expect(user2).toBeInTheDocument();
  expect(axios.get).toHaveBeenCalledTimes(1);
  expect(axios.get).toHaveBeenCalledWith('https://jsonplaceholder.typicode.com/users');
});

Method 2: Mocking with axios-mock-adapter

For complex applications with multiple API endpoints, post requests, or error handling, using axios-mock-adapter provides a cleaner, more declarative syntax.

Step 1: Install the Adapter

First, install the mock adapter package as a development dependency:

npm install axios-mock-adapter --save-dev

Step 2: Write the Test

Create an instance of the mock adapter and attach it to your Axios instance to intercept outgoing requests based on specific URLs and HTTP methods.

import React from 'react';
import { render, screen } from '@testing-library/react';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import UserList from './UserList';

// Create a new instance of the mock adapter
const mock = new MockAdapter(axios);

describe('UserList with axios-mock-adapter', () => {
  afterEach(() => {
    mock.reset(); // Reset mock handlers after each test
  });

  test('fetches and displays users', async () => {
    const mockUsers = [{ id: 1, name: 'Alice Johnson' }];
    
    // Intercept GET requests to the specific endpoint
    mock.onGet('https://jsonplaceholder.typicode.com/users').reply(200, mockUsers);

    render(<UserList />);

    const user = await screen.findByText('Alice Johnson');
    expect(user).toBeInTheDocument();
  });

  test('handles API errors gracefully', async () => {
    // Simulate a network/server error
    mock.onGet('https://jsonplaceholder.typicode.com/users').reply(500);

    render(<UserList />);
    
    // Assert error UI state if your component handles errors
  });
});