How to Test Axios Interceptors in React
Testing Axios interceptors in React ensures that outgoing requests
and incoming responses are modified correctly, such as automatically
attaching authorization tokens or handling global API errors. This guide
provides a straightforward approach to writing unit tests for both
request and response interceptors using Jest and
axios-mock-adapter.
Setting Up the Axios Instance
Before writing tests, you need an Axios instance with interceptors
configured. Below is an example of an API client that attaches a bearer
token to requests and handles 401 Unauthorized errors on
responses.
// api.js
import axios from 'axios';
const api = axios.create({
baseURL: 'https://api.example.com',
});
// Request Interceptor: Attach Auth Token
api.interceptors.request.use(
(config) => {
const token = 'mock-token'; // In production, retrieve this from storage or state
if (token) {
config.headers['Authorization'] = `Bearer ${token}`;
}
return config;
},
(error) => Promise.reject(error)
);
// Response Interceptor: Handle Global Errors
api.interceptors.response.use(
(response) => response,
(error) => {
if (error.response && error.response.status === 401) {
// Logic for handling unauthorized errors (e.g., redirect to login)
console.error('Unauthorized access - Redirecting...');
}
return Promise.reject(error);
}
);
export default api;Writing Tests with Axios Mock Adapter
To test these interceptors without making real network requests, use
axios-mock-adapter. This library allows you to mock the
Axios instance’s responses and inspect the configuration of the requests
sent through it.
First, install the mock adapter:
npm install axios-mock-adapter --save-devThe Test Suite
Create a test file to verify that the headers are correctly added to the request and that error responses are caught as expected.
// api.test.js
import MockAdapter from 'axios-mock-adapter';
import api from './api';
describe('Axios Interceptors', () => {
let mock;
beforeEach(() => {
// Create a mock instance bound to our custom API client
mock = new MockAdapter(api);
});
afterEach(() => {
// Reset the mock state after each test
mock.reset();
});
it('should inject the Authorization header in requests', async () => {
// Mock any GET request to return a 200 OK status
mock.onGet('/user').reply(200, { id: 1, name: 'John Doe' });
const response = await api.get('/user');
// Assert that the request interceptor successfully appended the token
expect(response.config.headers['Authorization']).toBe('Bearer mock-token');
expect(response.data).toEqual({ id: 1, name: 'John Doe' });
});
it('should intercept 401 response errors and handle them', async () => {
// Spy on console.error to check if the error handling logic is triggered
const consoleSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
// Mock a GET request to return a 401 Unauthorized status
mock.onGet('/secure-data').reply(401);
await expect(api.get('/secure-data')).rejects.toThrow();
// Verify that the response interceptor executed its error logic
expect(consoleSpy).toHaveBeenCalledWith('Unauthorized access - Redirecting...');
consoleSpy.mockRestore();
});
});Key Takeaways
- Isolate Axios: Use
axios-mock-adapterspecifically on your custom Axios instance (api) rather than the globalaxiosimport. - Inspect the Config Object: To test request
interceptors, assert on the properties of the returned
response.config.headers. - Assert Reject Promises: To test error interceptors,
use Jest’s
.rejects.toThrow()matcher to ensure failing statuses are processed correctly.