Mocking functions and modules with Jest
A JavaScript program can have several dependencies, internal and/or external, most likely represented by the list of imports on the very top of your script. To write deterministic, repeatable unit tests, we need to control the inputs, outputs and invocations of those dependencies. These objects that simulate the real objects are mocks. Let’s have a look at Wikipedia definition of Mock object.
Mock objects are simulated objects that mimic the behavior of real objects in controlled ways, most often as part of a software testing initiative.
There is plenty of JavaScript mocking libraries out there. Today I am going to review a few methods of creating functions and modules mock using my favourite testing framework, Jest.
To mock or not to mock?
Mocking all dependencies feels like a perfect solution. Who doesn’t like to have total control? Unfortunately it may cause many false positives, because we end up testing a particular scenario implemented in a particular way. It is not a reliable test of a produced result.
On the other hand, why should we use mocks at all? Won’t we get the most accurate results by testing software as it is implemented? Yes — but this is out of scope of a unit test. Unit test should be isolated, narrow in scope and quick to execute.
“Please don’t mock me” by Justin Searls on YouTube is a fantastic talk about things that should be mocked and where mocking should be avoided. “Mock Objects: Shortcomings and Use Cases” by Alex Ruiz is another resource that I found very helpful. If you have to mock too much then this may indicate a high degree of coupling in your application. “Mocking is a Code Smell” by Eric Elliott is a very helpful article that can help you to reduce tight coupling and a requirement of widespread mocking.
Mocking is required when our supposed atomic units of composition are not really atomic, and our decomposition strategy has failed to decompose the larger problem into smaller, independent problems.
These are my typical candidates for mocks:
- mock API calls
- mock databases queries
- mock conditions difficult to generate in a test environment

Jest mocks
The Jest testing framework comes with great mocking methods built-in for functions as well as modules. Let’s have a look at them all.
Function mock using jest.fn()
The simplest and most common way of creating a mock is jest.fn()
method. If no implementation is provided, it will return the undefined
value. There is plenty of helpful methods on returned Jest mock to control its input, output and implementation. Let’s have a look at a few examples.
it("returns undefined and has been called correct number of times", () => {
const mock = jest.fn();
const result = mock();
expect(result).toBeUndefined();
expect(mock).toHaveBeenCalledTimes(1);
expect(mock).toHaveBeenCalledWith();
});
it("has been called with correct arguments and returns a correct value", () => {
const mock = jest
.fn()
.mockReturnValueOnce("first return")
.mockReturnValueOnce("second return");
const resultFirst = mock("first call");
const resultSecond = mock("second call");
expect(resultFirst).toBe("first return");
expect(resultSecond).toBe("second return");
expect(mock).toHaveBeenCalledTimes(2);
expect(mock).toHaveBeenNthCalledWith(1, "first call");
expect(mock).toHaveBeenNthCalledWith(2, "second call");
});
Function mock using jest.spyOn()
Another method of creating a function mock is a jest.spyOn()
method. Same like jest.fn()
it creates a controlled mock. The key difference is the fact that by default it calls the original implementation. It stores in memory the original implementation so in case it has been redefined, jest.spyOn()
allows us to restore the initial implementation using mockRestore()
method. This is not something that we can do using jest.fn()
. Example:
// helpers.js
module.exports = {
add: (a, b) => a + b,
};
const helpers = require("./helpers");
it("returns correct result", () => {
const addMock = jest.spyOn(helpers, "add");
const result = addMock(1, 2);
// look, in contrast to jest.fn() that returns undefined by default
// jest.spyOn() calls original implementation
expect(result).toBe(3);
});
it("returns mocked and original result", () => {
const addMock = jest.spyOn(helpers, "add");
addMock.mockImplementation(() => 4);
// redefined implementation
expect(helpers.add()).toBe(4);
addMock.mockRestore();
// original implementation
expect(helpers.add(1, 2)).toBe(3);
});
I’m sorry for the terrible example above, this is because in real life you have no valid reasons to mock pure functions like add()
. This is purely for illustrative purpose.
Module mock using jest.mock()
To entirely mock a module we can do something like this…
// helpers.js
module.exports = {
add: (a, b) => a + b,
sub: (a, b) => a - b,
};
const helpers = require("./helpers");
it("mocks entire module", () => {
helpers.add = jest.fn();
helpers.sub = jest.fn();
expect(helpers.add.mock).toBeTruthy();
expect(helpers.sub.mock).toBeTruthy();
});
It works, but what if a module exports tens or hundreds of methods? Manually reassigning all of them would be cumbersome. Jest comes with a fantastic feature called automock
that you can enable globally or inside individual test files using jest.mock()
method.
const helpers = require("./helpers");
jest.mock("./helpers");
it("mocks entire module", () => {
expect(helpers.add.mock).toBeTruthy();
expect(helpers.sub.mock).toBeTruthy();
});
Much nicer, isn’t it? Internally Jest inspects the module and creates a mock that conforms to original’s exports. Pretty neat!
Hot tip — name your mock
Look at this test and its result.
it("calls a function", () => {
const mock = jest.fn();
expect(mock).toHaveBeenCalledTimes(1);
});
expect(jest.fn()).toHaveBeenCalledTimes(expected)
Expected number of calls: 1
Received number of calls: 0

This is OK if we have one test in a file, but it is hard to guess what jest.fn()
is in a hundred lines long file. There is a simple solution — give your mock a descriptive name using mockName()
method. Look!
it("calls a function", () => {
const mock = jest.fn().mockName("my dope mock");
expect(mock).toHaveBeenCalledTimes(1);
});
expect(my dope mock).toHaveBeenCalledTimes(expected)
Expected number of calls: 1
Received number of calls: 0

Hopefully you found this article helpful and you learned a thing or two. Until next time, stay curious!
Nice! Thx for your post!
Ooo, thanks! I am glad it helped you out!
Have a lovely day 🥑
thanks for the article. wanted to mock module with parameters , say i have add module and it return 3 when i pass value 1 and 2 and 4 when i pass 2 and 2. how this can be mocked ?
I wouldn't advice to mock pure functions like `sum`. Just hit an actual implementation to test it.
If you use `sum` just as an example, you need to look into something called `jest-when`.
import { when } from 'jest-when';
const fn = jest.fn()
when(fn)
.calledWith(1, 2).mockReturnValue(3)
.calledWith(2, 2).mockReturnValue(4);
expect(fn(1)).toEqual('yay!')
expect(fn(2)).toEqual('nay!')
thank you for taking time and responding, I saw jest-when but didn't really feel to use it. thanks for the recommendation and happy holidays and be safe :)
how to mock lambda function using jest
Hi Esai. There is nothing magical about Lambda functions. The trickiest part is to get the right shape of an event as a test value. I like to use
sam local generate-event
to help me with this one. It is one of the cool features of AWS SAM framework. Other than that, Lambdas are easy to test pure functions.How to mock toJSON() function?
Hi Pawel,
Thanks for the neat summary!
I just wanted to relate to this:
I have just yesterday had a situation where I needed to mock esModule, which is not possible, as far as I know, with
jest.mock()
, and then restore the original implementation in one of the next test in the same suite. After some time of research, I found this way to do it:Hope that helps someone!
Thank you for sharing your insights Jacek.
I am not sure how much Jest supports ES modules at this point, but I would expect some big changes on this space in relatively short future, as ES modules re more and more popular within Node.js ecosystem.
Thank you! The jest.spyOn saved me! I couldn't figure out for the life of me on how to mock the implementation of an Angular method.
Hello, sorry I don´t understand the differences between .mock() and .createMockFromModule(), seems to me that the only difference is that .mock() takes more parameters (jest.mock(moduleName, factory, options)) and you can pass the mocked implementation in the factory parameter but both work exactly the same. Can you please tell me the differences? I'd really appreciated it :)
Hi. The
jest.mock()
is explicit and manual way of mock creation, where thecreateMockFromModue()
is a helper that automatically mocks all the members exported from the module for you. They are not one to one.Could you please provide some insight on best way to mock functions in a file that are not exported
I am not sure if thats even possible. If you don't have an access to a direct member, I would suggest looking into other patters, like dependency injection that will allow you to entirely swap an implementation of a tested unit.
hi, i want to ask a question suppose the
demo.js
file has the following code:How have I tested that when a is executed, b is called correctly? The scheme given by ai is like this, but I did not pass it
This is tricky, especially when it comes to testing ESM, which is just experimental on jest at the time of writing this. Look at this comment please.