Best Patterns for Mocking Axios in Unit Tests

Mocking Axios in unit tests is essential for isolating application logic, preventing unintended network requests, and creating fast, deterministic test suites. This article covers the industry-standard patterns for mocking Axios, focusing on the dedicated axios-mock-adapter library, native test runner mocking using Jest or Vitest, and network-level interception with Mock Service Worker (MSW).


The most reliable and maintainable way to mock Axios specifically is using the axios-mock-adapter library. It integrates directly with Axios instances, allowing you to define route-specific responses, HTTP status codes, and network delays without overriding the prototype of Axios itself.

Installation

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

Implementation Example

import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import { fetchUserData } from './userService';

describe('fetchUserData', () => {
  let mock;

  beforeAll(() => {
    // Attach the mock adapter to the default axios instance
    mock = new MockAdapter(axios);
  });

  afterEach(() => {
    // Reset handlers between tests
    mock.reset();
  });

  afterAll(() => {
    // Restore original axios instance
    mock.restore();
  });

  it('returns data when the API call is successful', async () => {
    const mockResponse = { id: 1, name: 'Jane Doe' };
    mock.onGet('/users/1').reply(200, mockResponse);

    const data = await fetchUserData(1);
    expect(data).toEqual(mockResponse);
  });

  it('handles 404 errors appropriately', async () => {
    mock.onGet('/users/999').reply(404);

    await expect(fetchUserData(999)).rejects.toThrow();
  });
});

2. Using Jest or Vitest Built-In Mocks

If you prefer not to install third-party packages, you can mock the Axios module directly using Jest (jest.mock) or Vitest (vi.mock). This approach replaces Axios methods with mock functions.

Implementation Example (Jest)

import axios from 'axios';
import { fetchUserData } from './userService';

jest.mock('axios');

describe('fetchUserData with Jest Mocks', () => {
  afterEach(() => {
    jest.clearAllMocks();
  });

  it('fetches successfully data from an API', async () => {
    const mockUser = { id: 1, name: 'John Doe' };
    axios.get.mockResolvedValueOnce({ data: mockUser });

    const result = await fetchUserData(1);

    expect(axios.get).toHaveBeenCalledWith('/users/1');
    expect(result).toEqual(mockUser);
  });

  it('handles network failure', async () => {
    const errorMessage = 'Network Error';
    axios.get.mockRejectedValueOnce(new Error(errorMessage));

    await expect(fetchUserData(1)).rejects.toThrow(errorMessage);
  });
});

Note: When using custom Axios instances created with axios.create(), module-level mocking requires manually mocking the create method to return an object with mocked HTTP methods.


3. Mock Service Worker (MSW)

For broader test coverage across different HTTP clients (Axios, Fetch, etc.), Mock Service Worker intercepts requests at the network level rather than replacing JavaScript modules.

Implementation Example

import { setupServer } from 'msw/node';
import { rest } from 'msw';
import { fetchUserData } from './userService';

const server = setupServer(
  rest.get('/users/:id', (req, res, ctx) => {
    return res(ctx.json({ id: req.params.id, name: 'Alice' }));
  })
);

beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());

it('fetches user data via network-level mock', async () => {
  const data = await fetchUserData(1);
  expect(data).toEqual({ id: '1', name: 'Alice' });
});

Key Best Practices