How to Mock Network Latency in Axios Tests

Testing how applications handle slow network connections and loading states is essential for building resilient user interfaces. This article covers practical techniques to mock network latency when testing HTTP requests with Axios. You will learn how to introduce artificial delays using popular mocking libraries like axios-mock-adapter and Mock Service Worker (MSW), as well as how to implement custom delay interceptors for unit and integration tests.

1. Using axios-mock-adapter

The most straightforward way to simulate network latency with Axios is using the axios-mock-adapter library. It provides a built-in delayResponse configuration option that defers the mock response resolution by a specified number of milliseconds.

Installation

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

Implementation

import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';

describe('API Latency Tests', () => {
  let mock;

  beforeEach(() => {
    // Initialize mock adapter with a 1500ms delay
    mock = new MockAdapter(axios, { delayResponse: 1500 });
  });

  afterEach(() => {
    mock.restore();
  });

  it('handles slow response correctly', async () => {
    mock.onGet('/api/users').reply(200, [{ id: 1, name: 'Alice' }]);

    const startTime = Date.now();
    const response = await axios.get('/api/users');
    const duration = Date.now() - startTime;

    expect(response.status).toBe(200);
    expect(duration).toBeGreaterThanOrEqual(1500);
    expect(response.data).toEqual([{ id: 1, name: 'Alice' }]);
  });
});

2. Using Custom Axios Interceptors

If you prefer not to install extra dependencies, you can use Axios response interceptors to inject custom delay logic into your test environment.

Implementation

import axios from 'axios';

// Helper function to introduce delay
const createDelayInterceptor = (delayMs) => {
  return async (response) => {
    await new Promise((resolve) => setTimeout(resolve, delayMs));
    return response;
  };
};

describe('Axios Interceptor Delay', () => {
  let interceptorId;

  beforeEach(() => {
    // Add latency to all responses
    interceptorId = axios.interceptors.response.use(
      createDelayInterceptor(1000)
    );
  });

  afterEach(() => {
    // Eject interceptor to clean up
    axios.interceptors.response.eject(interceptorId);
  });

  it('delays response via interceptor', async () => {
    const start = Date.now();
    const response = await axios.get('https://jsonplaceholder.typicode.com/todos/1');
    const elapsed = Date.now() - start;

    expect(elapsed).toBeGreaterThanOrEqual(1000);
    expect(response.status).toBe(200);
  });
});

3. Using Mock Service Worker (MSW)

Mock Service Worker (MSW) intercepts requests at the network level and includes a native delay() utility to simulate realistic network latency across testing environments.

Installation

npm install --save-dev msw

Implementation

import axios from 'axios';
import { http, HttpResponse, delay } from 'msw';
import { setupServer } from 'msw/node';

const server = setupServer(
  http.get('/api/data', async () => {
    // Add artificial network delay of 2000ms
    await delay(2000);
    return HttpResponse.json({ message: 'Success' });
  })
);

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

it('simulates slow endpoint using MSW', async () => {
  const start = Date.now();
  const response = await axios.get('/api/data');
  const duration = Date.now() - start;

  expect(response.data).toEqual({ message: 'Success' });
  expect(duration).toBeGreaterThanOrEqual(2000);
});

Testing Timeouts and UI Loading States

Mocking network latency is particularly useful for verifying UI loading indicators and handling request timeouts.

import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';

it('triggers an Axios timeout error when latency exceeds timeout limit', async () => {
  const mock = new MockAdapter(axios, { delayResponse: 3000 });
  mock.onGet('/api/slow-endpoint').reply(200);

  const client = axios.create({
    timeout: 1000, // 1-second timeout
  });

  await expect(client.get('/api/slow-endpoint')).rejects.toThrow('timeout of 1000ms exceeded');

  mock.restore();
});