• Jest

Using jest mockImplementationOnce to mock multiple return values

March 03, 2022 • 1 min read

This is a useful trick for mocking functions that return different values after x calls

Sometimes you may need to mock a function such that it returns different values after x number of calls. Using the mockImplementationOnce method from a mock function will allow you to do this. Let's look at an example.


In the following code, we have created a mock function and provided it default implementations.

Usage

1
it("mocks multiple values", () => {
2
const testFunc = jest
3
.fn()
4
.mockImplementationOnce(() => 1)
5
.mockImplementationOnce(() => 2)
6
.mockImplementation(() => 3);
7
8
const a = testFunc();
9
const b = testFunc();
10
const c = testFunc();
11
12
expect(a).toBe(1);
13
expect(b).toBe(2);
14
expect(c).toBe(3);
15
});

As you can see, with each call of testFunc, it will return a value based on the order that mockImplementationOnce was called. However, for the last call, 3 is returned. This is because the third time we mock testFunc's implementation, we use mockImplementation which will act as the default.


It will also return 3 for any other calls after the third one.

1
it("mocks multiple values", () => {
2
// previous code
3
expect(a).toBe(1);
4
expect(b).toBe(2);
5
expect(c).toBe(3);
6
expect(testFunc()).toBe(3)
7
expect(testFunc()).toBe(3)
8
});

Another Example

You can also provide the mock function a default implementation without calling mockImplementation, by passing the default mock the fn() call.


1
it("mocks multiple values", () => {
2
const testFunc = jest
3
.fn(() => 3)
4
.mockImplementationOnce(() => 1)
5
.mockImplementationOnce(() => 2)
6
7
const a = testFunc();
8
const b = testFunc();
9
const c = testFunc();
10
11
expect(a).toBe(1);
12
expect(b).toBe(2);
13
expect(c).toBe(3);
14
expect(testFunc()).toBe(3);
15
});

Real World Usage

Anytime you are testing a function that has it's return values dependent on some kind of loop, this can be helpful. For example, when the loop first runs, you expect x to be returned, second time it runs, you expect y, and so forth.


A more concrete example is uploading data in chunks through a remote server API. When you read the first x set of chunked data you may expect a response telling you the upload is in progress and what byte ranges are left to be read. Then on the last chunk upload, you may expect the response to contain a JSON object containing information about the uploaded data.


In turn, when writing your tests, you can use mockImplementationOnce to mock those different API responses and make sure your code is working as expected.