Testing Axios API Calls with Jest Mocks
Testing API calls is a fundamental part of building robust applications, ensuring your code handles network responses and errors predictably. This article demonstrates how to unit test Axios HTTP requests using Jest by creating mock implementations of the Axios client. You will learn how to mock network responses, verify request parameters, and test both successful responses and error states without sending actual HTTP requests to an external server.
1. The Module Under Test
Consider a simple service file, userService.js, that
uses Axios to fetch and post user data:
// userService.js
import axios from 'axios';
export const getUser = async (id) => {
try {
const response = await axios.get(`https://api.example.com/users/${id}`);
return response.data;
} catch (error) {
throw new Error('Failed to fetch user');
}
};
export const createUser = async (userData) => {
const response = await axios.post('https://api.example.com/users', userData);
return response.data;
};2. Mocking Axios with
jest.mock()
To prevent actual network requests during testing, use
jest.mock('axios'). This replaces the Axios module with an
auto-mocked version where all methods (get,
post, put, delete, etc.) are Jest
mock functions.
// userService.test.js
import axios from 'axios';
import { getUser, createUser } from './userService';
// Mock the entire axios module
jest.mock('axios');
describe('userService', () => {
afterEach(() => {
jest.clearAllMocks();
});
// Tests go here...
});Using jest.clearAllMocks() in the afterEach
hook ensures that call counts and mock implementations do not leak
across different tests.
3. Testing Successful GET Requests
To test a successful API call, mock the resolved value of the Axios
method using mockResolvedValue or
mockResolvedValueOnce:
test('getUser fetches successfully data from an API', async () => {
const mockUser = { id: 1, name: 'Jane Doe' };
// Set up the mock response structure
axios.get.mockResolvedValueOnce({ data: mockUser });
const result = await getUser(1);
// Assertions
expect(axios.get).toHaveBeenCalledTimes(1);
expect(axios.get).toHaveBeenCalledWith('https://api.example.com/users/1');
expect(result).toEqual(mockUser);
});4. Testing Error Scenarios and Rejections
To verify that your application handles network failures or API
errors gracefully, use mockRejectedValue or
mockRejectedValueOnce:
test('getUser throws an error when the API call fails', async () => {
// Simulate a network failure or 500 status code
axios.get.mockRejectedValueOnce(new Error('Network Error'));
await expect(getUser(1)).rejects.toThrow('Failed to fetch user');
expect(axios.get).toHaveBeenCalledWith('https://api.example.com/users/1');
});5. Testing POST Requests and Payloads
When testing requests that send data (such as POST or
PUT), verify that the payload passed to the Axios method
matches the expected schema:
test('createUser sends the correct payload and returns new user', async () => {
const newUser = { name: 'John Doe', email: 'john@example.com' };
const mockResponse = { id: 2, ...newUser };
axios.post.mockResolvedValueOnce({ data: mockResponse });
const result = await createUser(newUser);
expect(axios.post).toHaveBeenCalledTimes(1);
expect(axios.post).toHaveBeenCalledWith('https://api.example.com/users', newUser);
expect(result).toEqual(mockResponse);
});6. Mocking Axios
Instances (axios.create)
If your application uses custom Axios instances created via
axios.create(), you must mock the create
method to return an object containing mocked methods:
// If using custom instances:
jest.mock('axios', () => {
const mAxios = {
get: jest.fn(),
post: jest.fn(),
};
return {
create: jest.fn(() => mAxios),
...mAxios,
};
});This pattern guarantees that whether your application code calls
axios.get() directly or calls methods on an instance
generated by axios.create(), the mock functions intercept
the execution.