# Quickest Way to Mock Module Dependencies with Jest

[Rodolfo Gobbi](https://www.strv.com/blog/authors/rodgobbi) Frontend Engineer

---

Jest offers many features out of the box. One that is very powerful and commonly used in unit tests is the auto mock feature, which is when Jest automatically mocks everything exported by a module that is imported as a dependency by any module we are testing. Due to Jest’s extensive list of features, the auto mock feature can be easily missed—especially because the documentation doesn’t explicitly focus on it (it’s mentioned in the [The Jest Object](https://jestjs.io/docs/en/jest-object?ref=strv.ghost.io#jestmockmodulename-factory-options), [Mock Function](https://jestjs.io/docs/en/mock-functions?ref=strv.ghost.io#mocking-modules) and [ES6 Class Mocks](https://jestjs.io/docs/en/es6-class-mocks?ref=strv.ghost.io#automatic-mock) sections).

In this article, we’ll cover the simplest and quickest way of mocking any dependency—external or internal—with Jest just by calling `jest.mock`, without changing the implementation of the modules.

## MOCKING AN EXTERNAL DEPENDENCY

Suppose we have these extracted API calls using [axios](https://github.com/axios/axios?ref=strv.ghost.io):

```js
// api/users.js
import axios from 'axios';

export const getUsers = async () => {
  const { data } = await axios.get('/api/users');
  return data;
};

export const getUserData = async (id) => {
  const { data } = await axios.get(`/api/user/${id}`);
  return data;
};
```

If we want to unit test this simple function and don't want to call the API every time the test runs, we can solve this by simply calling `jest.mock`:

```js
// __tests__/api/users.js
import axios from 'axios';
import { getUsers, getUserData } from '../../api/users';

jest.mock('axios');

const axiosGet = axios.get;

beforeEach(() => {
  axiosGet.mockReset();
});

describe('getUsers', () => {
  it('should call the API and return the data', async () => {
    const usersData = [
      { id: 51, name: 'Allan' },
      { id: 120, name: 'George' },
    ];

    axiosGet.mockResolvedValue({ data: usersData });

    // also could be mockImplementation
    // or anything that mock functions can do

    const returnedUsersData = await getUsers();

    expect(returnedUsersData).toEqual(usersData);
    expect(axiosGet).toHaveBeenCalledTimes(1);
    expect(axiosGet).toHaveBeenCalledWith('/api/users');
  });

  it('should get user data by id', async () => {
    const userId = 51;
    const userData = { id: userId, name: 'Allan' };
    axiosGet.mockResolvedValue({ data: userData });

    const returnedUserData = await getUserData(userId);

    expect(returnedUserData).toEqual(userData);
    expect(axiosGet).toHaveBeenCalledWith(`/api/user/${userId}`);
  });
});
```

We can call `jest.mock('axios')` after importing axios because Jest will [hoist](https://developer.mozilla.org/en-US/docs/Glossary/Hoisting?ref=strv.ghost.io) all `jest.mock` calls to the top of the file. ([Reference](https://jestjs.io/docs/en/es6-class-mocks?ref=strv.ghost.io#calling-jestmockdocsenjest-objectjestmockmodulename-factory-options-with-the-module-factory-parameter))

When we call `jest.mock('axios')`, both the `axios` module imported in the test and the module imported by `users.js` will be the mocked version and the same one imported in this test.

We need to reset the `axios.get` mock before each test because all tests in the file share the same mock function. (In this case, we could achieve the same with [mockClear](https://jestjs.io/docs/en/mock-function-api?ref=strv.ghost.io#mockfnmockclear), but [mockReset](https://jestjs.io/docs/en/mock-function-api?ref=strv.ghost.io#mockfnmockreset) is safer.)

If we were using TypeScript and wanted type safety for the mock functions, we could write:

```js
const axiosGet = axios.get as jest.Mock;
```

We need to type cast the function because without doing so, TS wouldn't recognize `axios.get` as a mock.

## MOCKING AN INTERNAL DEPENDENCY

Suppose we have a module that does more complex data processing:

```js
// utils/getSortedUserData.js
import { getUserData } from '../api/users';

const getSortedUserData = async (id) => {
  const userData = await getUserData(id);
  const contactsSortedByName = [...userData.contacts]
    .sort((a, b) => {
      // implementation details are not relevant to this article
    });
  // ...
  return {
    user: userData,
    contactsSortedByName,
    contactsSortedByAge,
  };
};

export default getSortedUserData;
```

...and suppose we want to test if we are processing the data correctly. In this case, we could use `jest.mock` for either `axios` or `getUserData`, but for the purpose of mocking internal modules, our example will mock `users.js`:

```js
// __tests__/utils/getSortedUserData.js
import { getUserData } from '../../api/users';
import getSortedUserData from '../../utils/getSortedUserData';

jest.mock('../../api/users');

describe('getSortedUserData', () => {
  it('should get user data and sort the contacts', async () => {
    const userId = 51;
    const userData = {
      id: userId,
      name: 'Allan',
      // the detailed data are not relevant to this article
      contacts: [...],
    };
    const expectedSortedUserData = {
      contactsSortedByName: [...],
      contactsSortedByAge: [...],
    };
    getUserData.mockResolvedValue(userData);

    const sortedUserData = await getSortedUserData(userId);

    expect(sortedUserData).toEqual(expectedSortedUserData);
    expect(getUserData).toHaveBeenCalledTimes(1);
    expect(getUserData).toHaveBeenCalledWith(userId);
  });
});
```

When we mock an internal module, we use the path to the target module related to the test file where we call `jest.mock`, not the path used by the modules being tested.

Also worth pointing out is that we import anything exported by the mocked module in the same way it was exported, whether named exports or default export.

## CONCLUSION

A simple `jest.mock` call allows us to intercept any dependency of the modules we are testing, without needing to change anything in implementation. Jest exposes everything exported by the mocked module as mock functions, which we can manipulate in our tests. It also lets us assert that the modules being tested are using the mocked module properly.

## FURTHER READING

`jest.mock` accepts two more arguments: a [module factory](https://jestjs.io/docs/en/es6-class-mocks?ref=strv.ghost.io#calling-jestmockdocsenjest-objectjestmockmodulename-factory-options-with-the-module-factory-parameter), which returns the mock implementation, and an [object](https://jestjs.io/docs/en/jest-object?ref=strv.ghost.io#jestmockmodulename-factory-options) that can create virtual mocks—mocks of modules that don’t exist in the system.

Using the module factory usually requires more work because of differences between CommonJS and ES6 modules. These differences should be considered.

The second argument may be necessary when:

- Jest cannot auto-mock an external module (e.g., only available in a minified build).
- You need to mock part of a module while keeping the original implementation for some exported properties.

For more in-depth guidance on mocking modules with Jest, including the use of the second argument, see [Jest Full and Partial Mock/Spy of CommonJS and ES6 Module Imports](https://codewithhugo.com/jest-mock-spy-module-import/?ref=strv.ghost.io).

*Article originally published on* [https://rodgobbi.com/](https://rodgobbi.com/?ref=strv.ghost.io).