Jest: mockFn.clearMock() should remove function implementations and return values

Created on 29 Apr 2015  路  8Comments  路  Source: facebook/jest

I think that clearMock should clear out any return values defined with mockReturnValue(), mockReturnValueOnce(), and mockReturnThis as well as functions defined with mockImplementation().

My reasoning is that I just wasted a bunch of time debugging a test because that's what I thought it did.

My tests usually include defining the return value of mocked functions with mockReturnValueOnce() and this return value will often change between tests because I'm setting up different conditions. I'll use mockClear() in a beforeEach() block to clear our the mock. I think this is pretty normal.

The problem I was debugging involved two mocked functions returning boolean values. e.g.

Whatzit.mocked1.mockReturnValue(/*boolean*/);
Whozit.mocked2.mockReturnValue(/*boolean*/)
if( Whatzit.mocked1() && Whozit.mocked2() ) {
  foo();
}

And expecting foo() to be called or not called depending on the return values. This has been working fine, mostly, but in this case I had previously mocked values invading later tests, because if Whatzit.mocked1() returned false, then because of short-circuiting Whozit.mocked2() was never called and that return value defined with mockReturnValueOnce() would then be used in the next test. This behaviour is great for giving different return values for subsequent calls, but bad when you think you've reset the mock.

Mostly I want a way to be sure that state from one test won't leak into another test.

Most helpful comment

@cpojer We've run into this same issue. Is there any reason that you wouldn't want mockClear to clear return values? The above workaround is especially clunky if you're using imports rather than requires.

All 8 comments

If you require your modules in beforeEach you won't be running into this problem and every call to it will receive a new module environment:

var A;
beforeEach(() => { A = require('A'); });

it('test 1', () => doSomethingWith(A));
it('test 2', () => doSomethingElseWith(A));

both calls to it will receive different versions of A.

I understand there's many ways to work around this, but the function _clearMock()_ should still clear the mock. And "clear" to me means "return to initial state".

There's also the fact that re-requiring before every test isn't free. I have several tests that do this and they all run significantly slower than those that just require once.

@cpojer We've run into this same issue. Is there any reason that you wouldn't want mockClear to clear return values? The above workaround is especially clunky if you're using imports rather than requires.

I too was surprised that clearing mocks doesn't clear mocked return values. Together with mockReturnValueOnce, I'm finding that this behavior can cause strange cascading failures. Test 1 fails early, before one of the mock return values is consumed, so unrelated test 2 fails.

@graue @mrsharpoblunto please feel free to send a PR to fix this behavior.

@cpojer Since you acknowledge a fix is desirable, will you please re-open this issue?

Sure, if you send a PR with a test :P

We have jest.resetAllMocks() and fn.mockReset() now.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

StephanBijzitter picture StephanBijzitter  路  3Comments

kentor picture kentor  路  3Comments

ticky picture ticky  路  3Comments

kgowru picture kgowru  路  3Comments

stephenlautier picture stephenlautier  路  3Comments