Jest: Invalid hook call after `jest.resetModules` for dynamic `require`s

Created on 29 Sep 2019  路  9Comments  路  Source: facebook/jest

馃悰 Bug Report

Invalid hook call when using jest.resetModules or jest.resetModuleRegistry
with dynamic require in test

To Reproduce

Steps to reproduce the behavior:
steps

Expected behavior

No invalid hook call

Link to repl or repo (highly encouraged)

demo repo

envinfo

  System:
    OS: macOS Mojave 10.14.6
    CPU: (8) x64 Intel(R) Core(TM) i7-4850HQ CPU @ 2.30GHz
  Binaries:
    Node: 10.16.3 - ~/.nvm/versions/node/v10.16.3/bin/node
    Yarn: 1.17.3 - /usr/local/bin/yarn
    npm: 6.11.3 - ~/.nvm/versions/node/v10.16.3/bin/npm
  npmPackages:
    jest: 24.9.0 => 24.9.0
Bug Report Needs Repro Needs Triage

Most helpful comment

@kapral18 We are also experiencing the same issue. Have you found a work around for this?

All 9 comments

I am also facing the same issues when I import react component(using hooks inside the component) using require and jest.resetModules() in the test.

@kapral18 We are also experiencing the same issue. Have you found a work around for this?

Same issue here

@lukevella Sorry for late response.

Here is what I came up with:
Screen Shot 2019-11-12 at 17 37 08

Seems like if you wrap each jest.doMock() call into a jest.isolateModules() call in each test, - it actually re-mocks the modules, as opposed to basic behavior when the mocks are unchanged.

And when you need to "reset" the mock, you doMock it again but with jest.requireActual call.

I have also been running into this issue in a particularly nasty way. We use the resetModules config option globally, so tricks around calling jest.isolateModules() don't work well. Instead, I came up with a workaround that globally excludes React from jest's resetModules behavior.

In a file specified in the setupFiles config option, add the following:

let mockActualReact;

jest.doMock(moduleName, () => {
  if (!mockActualReact) {
    mockActualReact = jest.requireActual('react');
  }
  return mockActualReact;
});

This sets up a mock for React that lazily loads the actual React, and always returns the result of the first initialization. This could also be generalized to implement a _set_ of modules that are globally excluded from resetModules.

Generalized version:

const RESET_MODULE_EXCEPTIONS = [
  'react',
  'react-redux',
];

let mockActualRegistry = {};

RESET_MODULE_EXCEPTIONS.forEach(moduleName => {
  jest.doMock(moduleName, () => {
    if (!mockActualRegistry[moduleName]) {
      mockActualRegistry[moduleName] = jest.requireActual(moduleName);
    }
    return mockActualRegistry[moduleName];
  });
});

Personally, I've found this to be a useful construct, and now that the React hook issue is more prevalent, it might be good to have a version of this built in to Jest as something like a persistentModules or excludeFromResetModules option.

I had the same issue, instead of making any changes in setup files I end up with using https://jestjs.io/docs/en/jest-object.html#jestisolatemodulesfn in order to isolate each module so they are imported without having cache.

ex.

import { render } from '@testing-library/react';
import React from 'react';

const { getPlatform } = require('device');
jest.mock('device');

describe('', () => {
    it('should render succesfully', () => {
        getPlatform.mockImplementation(() => 'desktop');
        jest.isolateModules(() => {
            const { SomeComponent } = require('./SomeComponent');

            const { container } = render(
                <SomeComponent>test</SomeComponent>
            );

            expect(container).toMatchSnapshot();
        });
    });
});

I tried to debug Jest. I found that this issue is caused by this._moduleRegistry.clear(); in a resetModules function. So, I remove that line and it works.

Not sure what happened inside a function. But hope this information helps someone that can fix this issue.

Thank you all so much. This was killing me all afternoon!

Thanks a lot, @quickgiant, your suggested solution https://github.com/facebook/jest/issues/8987#issuecomment-584898030 worked for us.

Was this page helpful?
0 / 5 - 0 ratings