Is it possibly for JEST mocks to be overwritten by each other?

Viewed 1247

I have two tests that look something like:

import someThing from '../someThing';
jest.mock('../someThing');

describe('group', () => {
    it('test #1', async () => {
        someThing.someFunction.mockImplementation(() => 123);
    });
    it('test #2', async () => {
        someThing.someFunction.mockImplementation(() => 456);
    });
});

I'm seeing an issue where it appears the mockImplementation from the first test is being called in the second test. If I disable test #1 test# 2 works as expected. (My actual code is more complicated than this).

The reason I need a separate mock for both is that one is supposed to return a failure result and one is supposed to return a success one given the same input.

From what I understand, JEST runs all test in parallel so I'm assuming what's happening is that the mockImplementation is being modified by both tests at the same time as it's the same import.

2 Answers

From the Mock Implementations docs:

The mockImplementation method is useful when you need to define the default implementation of a mock function that is created from another module

When you need to recreate a complex behavior of a mock function such that multiple function calls produce different results, use the mockImplementationOnce method

For your case:

import someThing from '../someThing';
jest.mock('../someThing');

describe('group', () => {
    it('test #1', async () => {
        someThing.someFunction.mockImplementationOnce(() => 123);
    });
    it('test #2', async () => {
        someThing.someFunction.mockImplementationOnce(() => 456);
    });
});

It's virtually never desired for tests to affect each other.

As a rule of thumb, Jest spies need to be restored to original state between tests:

beforeEach(() => {
  jest.restoreAllMocks();
  jest.clearAllMocks();
});

Or preferably applied to all tests unconditionally with Jest restoreMocks and clearMocks configuration options.

Not doing this results in test cross-contamination.

A workaround is to use *Once methods, as another answer describes. When used together with *restore*, they are only needed for sequential mocks within a single test.

From what I understand, JEST runs all test in parallel

Jest runs test files in parallel. As for single tests, this isn't the case, unless concurrent tests are in use.

Related