March 03, 2022 • 1 min read
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.
1it("mocks multiple values", () => {2const testFunc = jest3.fn()4.mockImplementationOnce(() => 1)5.mockImplementationOnce(() => 2)6.mockImplementation(() => 3);78const a = testFunc();9const b = testFunc();10const c = testFunc();1112expect(a).toBe(1);13expect(b).toBe(2);14expect(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.
1it("mocks multiple values", () => {2// previous code3expect(a).toBe(1);4expect(b).toBe(2);5expect(c).toBe(3);6expect(testFunc()).toBe(3)7expect(testFunc()).toBe(3)8});
You can also provide the mock function a default implementation without calling mockImplementation
, by passing the
default mock the fn()
call.
1it("mocks multiple values", () => {2const testFunc = jest3.fn(() => 3)4.mockImplementationOnce(() => 1)5.mockImplementationOnce(() => 2)67const a = testFunc();8const b = testFunc();9const c = testFunc();1011expect(a).toBe(1);12expect(b).toBe(2);13expect(c).toBe(3);14expect(testFunc()).toBe(3);15});
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.