jest-resolve not honoring require cache

Created on 18 Dec 2017  路  10Comments  路  Source: facebook/jest

Do you want to request a _feature_ or report a _bug_? Bug

What is the current behavior? jest-resolve or some other module does not honor require.cache

If the current behavior is a bug, please provide the steps to reproduce and
either a repl.it demo through https://repl.it/languages/jest or a minimal
repository on GitHub that we can yarn install and yarn test.

https://github.com/OzairP/jest-require-cache-no-honor

What is the expected behavior?
Tests should pass

Please provide your exact Jest configuration and mention your Jest, node,
yarn/npm version and operating system.

node: v8.6.0
npm: 5.3.0
yarn: 1.3.2
jest: 22.0.0

My current project hosts a tiny dependency injection container that is a singleton. When the app is setup it registers dependencies but in my tests I'm unable to mock my dependencies through my own container since the singleton is not shared between the test and the app.

Console screenshot: Note "index.js has someDep" line, this is from the setup
console

Most helpful comment

@ekeric13 I spent several hours trying to understand several, seemingly cryptic, comments on how to get singletons working in Jest. I was finally able to get this working with the below configuration that I gleaned from this comment. For reference, the singleton I am mocking is a module for setting global configuration values for a Next.js app.

// jest.setup.js
import mockEnvConfig from '~/env-config.js';

jest.mock('next/config', () => () => ({ publicRuntimeConfig: mockEnvConfig }));

// jest.config.js
module.exports = {
  setupFiles: ['<rootDir>/jest.setup.js'],
};

All 10 comments

Jest does not implement require.cache. This is by design. If you want to wipe all modules, run jest.resetModules() in your test code.

@cpojer when/where should jest.resetModules() be called. Is there any way to run jest without the jest-resolve or the patched require?

when/where should jest.resetModules() be called.

You can do it in an afterEach for instance, and have the requires in your tests.

Is there any way to run jest without the jest-resolve or the patched require

No. resetModules should be enough for your use case though, wherever you have your delete require.cache today

@SimenB I read through what jest.resetModules does and it is not the correct solution to my issue.

My issue is that any singletons like my DI Container I have in my project, which works based on require.cache. However, in my testing environment, any require'd singletons are reset without the cache.

My wish is to require any singletons through require.cache so I receive the same instance as I do from the project itself.

@SimenB please do check the sample project. The singleton class is the same pattern I'm using in my projects. Let me know if I can clarify anything.

https://github.com/OzairP/jest-require-cache-no-honor

@OzairP did you ever find a solution to this?

@Bradcomp

I made sure to register any singletons before running any tests, they should not register in any beforeEach/Any hooks.

@OzairP What do you mean by "register"? And are you "registering" them in the globalSetup file?

@ekeric13 I spent several hours trying to understand several, seemingly cryptic, comments on how to get singletons working in Jest. I was finally able to get this working with the below configuration that I gleaned from this comment. For reference, the singleton I am mocking is a module for setting global configuration values for a Next.js app.

// jest.setup.js
import mockEnvConfig from '~/env-config.js';

jest.mock('next/config', () => () => ({ publicRuntimeConfig: mockEnvConfig }));

// jest.config.js
module.exports = {
  setupFiles: ['<rootDir>/jest.setup.js'],
};

I was specifically looking in the documentation for the jest way of testing a singleton, what is normally accomplished with simply modifying the require.cache. I couldn't find what I was looking for and ended up on this old issue instead. So for anyone else that does I used jest.isolateModules(fn):

// Spec for testing event-bus.js
let eventBus

// Tear down stateful services
beforeEach(() => {
  jest.isolateModules(() => {
    eventBus = require('./event-bus')
  })  
})

Note that jest is the globally provided jest variable. Don't require/import jest because you'll just shadow it and the function will be undefined.

Was this page helpful?
0 / 5 - 0 ratings