`mock<X>Once` methods seem to be first-in first-out (unlike `mock<X>` methods)
See original GitHub issue🐛 Bug Report
This could be a result of me misusing mocks in a manner that shouldn’t be done, but basically the order that mock<X>Once calls resolve in seems to be first-in, first-out.
This to me doesn’t make sense, as I’d expect them to to be first-in, last-out, as that would match the order that they’re registered in code, so that “deeper” mock implementations would override “shallower” ones (which is the behaviour of the mock<X> methods).
This is particularly nasty as it means if you have a test that fails before a mock<X>Once call would happen, it can cause a cascade of test failures, due to off-by-1 error.
To Reproduce
Steps to reproduce the behavior:
describe('mockOnce', () => {
const mockFn = jest.fn();
beforeEach(() => jest.clearAllMocks());
describe('strings', () => {
beforeEach(() => {
console.log('strings > beforeEach');
mockFn.mockReturnValueOnce('a');
});
it('is a function', () => {
console.log('strings > it > is a function');
expect(typeof mockFn).toBe('function');
});
it('returns a string', () => {
console.log('strings > it > returns a string');
expect(typeof mockFn()).toBe('string');
});
});
describe('numbers', () => {
beforeEach(() => {
console.log('numbers > beforeEach');
mockFn.mockReturnValueOnce(1);
});
it('is a function', () => {
console.log('numbers > it > is a function');
expect(typeof mockFn).toBe('function');
});
it('returns a number', () => {
console.log('numbers > it > returns a number');
expect(typeof mockFn()).toBe('number');
});
});
});
Outputs:
FAIL ./add-test.js
mockOnce
strings
✓ is a function (11ms)
✓ returns a string (2ms)
numbers
✓ is a function (1ms)
✕ returns a number (60ms)
● mockOnce › numbers › returns a number
expect(received).toBe(expected) // Object.is equality
Expected value to be:
"number"
Received:
"string"
31 | it('returns a number', () => {
32 | console.log('numbers > it > returns a number');
> 33 | expect(typeof mockFn()).toBe('number');
34 | });
35 | });
36 | });
at Object.it (add-test.js:33:31)
console.log add-test.js:8
strings > beforeEach
console.log add-test.js:13
strings > it > is a function
console.log add-test.js:8
strings > beforeEach
console.log add-test.js:17
strings > it > returns a string
console.log add-test.js:23
numbers > beforeEach
console.log add-test.js:28
numbers > it > is a function
console.log add-test.js:23
numbers > beforeEach
console.log add-test.js:32
numbers > it > returns a number
Test Suites: 1 failed, 1 total
Tests: 1 failed, 3 passed, 4 total
Snapshots: 0 total
Time: 1.119s
Ran all test suites.
Expected behavior
All the tests pass, as they would if you use mockReturn instead of mockReturnOnce.
Link to repl or repo (highly encouraged)
repl.
Run npx envinfo --preset jest
Paste the results here:
System:
OS: Windows 10
CPU: (8) x64 Intel(R) Core(TM) i7-6700HQ CPU @ 2.60GHz
Binaries:
Node: 10.15.3 - C:\nodejs\node.EXE
Yarn: 1.13.0 - ~\AppData\Roaming\npm\yarn.CMD
npm: 6.9.0 - ~\AppData\Roaming\npm\npm.CMD
Issue Analytics
- State:
- Created 4 years ago
- Comments:7 (4 by maintainers)

Top Related StackOverflow Question
But I’m not saying they should be discarded 😕
I just tested your code, and that works (of course) - I swear in the past I was having the opposite behaviour, which lead me to initially conclude that your code would have the opposite result: since
mockReturnValuewas called last, it’d be called first.Now that I think about it, what I encountered when I first started using
jestmust has been thatmockReturnValuehas a higher precedence thanmockImplementation.~> All Once mocks and also all non-Once mocks~
~I’m guessing
jestdoesn’t want to expand their api to support this as a feature? (i.eclearAllMockOnces)~~Ideally I’m trying to save having to call
mockImplementationin a top-levelbeforeEach, and then have to keep in mind whenever I call a~The whole thing would just be too big of a breaking change for
jest. I’ll just have to adjust my thinking and be extra careful with my mocks.Thanks for taking the time to clarify this all for me 😄
If another
Oncecall discards the lastOncecall, you can’t doanymore (except by implementing it yourself in user code).
All
Oncemocks and also all non-Oncemocks