Mocking functions in Jest can be a powerful tool for testing your code, but sometimes you just want to mock one function from a module while leaving the others intact. Here's how to do it.
Let's say you're working on a project where you're making REST API requests to a third-party service to retrieve user data. You have a module called userService
that contains functions for these requests, such as getUserById
or listUsers
. Internally, these functions use the request
function from the rest-api-request
module to execute the REST API query.
However, the API is rate-limited, and you want to avoid exceeding the rate limit during your tests. Therefore, you decide to mock the request
function to return a fake user object, but leave the rest of the implementation unchanged to avoid side effects.
import userService from './userService';
import { request } from 'rest-api-request';
jest.mock('rest-api-request', () => {
const original = jest.requireActual('rest-api-request');
return {
...original,
request: jest.fn(() => ({
id: 1,
name: 'John Doe',
email: 'john.doe@example.com',
})),
};
});
In this example, we use the jest.mock()
function to create a mock for rest-api-request
. Then we use the jest.requireActual()
function to get the original implementation of rest-api-request
. The original module is spread to a new object and the request
function is overwritten with a mock implementation using jest.fn()
. In this case, the mock implementation returns only a dummy user object.
Next, this is how we would test our userService
:
describe('userService', () => {
test('Should call the REST API and return a user object', async () => {
const id = 1;
const params = {
endpoint: `/users/${id}`,
method: 'GET',
};
const expectedUser = {
id,
name: 'John Doe',
email: 'john.doe@example.com',
};
const user = await userService.getUserById(id);
// test user object was returned from mock function
expect(user).toEqual(expectedUser);
// test mock function was called once with correct parameters
expect(request).toHaveBeenCalledTimes(1);
expect(request).toHaveBeenCalledWith(params)
});
});
In this test, we set up the objects that the mock function should receive and return. Then we call getUserById
with an ID, which would normally trigger a call to request
to execute the REST API query, but will stop at our mock function. Finally, we use Jest's toHaveBeenCalledTimes()
and toHaveBeenCalledWith()
matchers to check that request
was called once and with the correct parameters.
Overall, this approach allows us to test the functionality of our user service module while ensuring that it uses the request
function correctly. Using this technique, we can selectively mock functions in dependent modules without affecting the functionality of the module itself.
Top comments (0)