- Clone the repository:
git clone git@github.com:klocke-io/jestHoistingTest.git cd jestHoistingTest - Install dependencies:
npm install
- Run specific test files:
For the
.jstest: (Works as expected ✅)For thenpx jest __tests__/index.spec.js
.cjstest: (Dose not work as expected ❌)For the manually hoistednpx jest __tests__/index.spec.cjs
.cjstest (Works as expected ✅):npx jest __tests__/index.manually-hoisted.cjs
This repository demonstrates a potential bug in Jest related to the hoisting of jest.mock when using .cjs file extension for test files.
-
lib/index.js: Exports a function
businessMessagethat returns'foo bar'.// lib/index.js function businessMessage() { return 'foo bar'; } module.exports = { businessMessage };
-
tests/index.spec.js: ✅ Standard Jest test in CommonJS, with
jest.mockafter therequire. This works as expected because Jest hoists the mock.// __tests__/index.spec.js const { businessMessage } = require('../lib'); jest.mock('../lib', () => ({ businessMessage: jest.fn(() => 'mocked!'), })); test('should use the mocked implementation', () => { expect(businessMessage()).toBe('mocked!'); });
-
tests/index.spec.cjs: ❌ Identical to the
.jstest, but with a.cjsextension. Here,jest.mockis not hoisted, so the real implementation is used instead of the mock.// __tests__/index.spec.cjs const { businessMessage } = require('../lib'); jest.mock('../lib', () => ({ businessMessage: jest.fn(() => 'mocked!'), })); test('should use the mocked implementation', () => { expect(businessMessage()).toBe('mocked!'); }); // This test will fail because jest.mock is not hoisted in .cjs files
-
tests/index.manually-hoisted.cjs: ✅ The mock is placed before the
requirestatement, manually simulating hoisting. This test works as expected, even with the.cjsextension.// __tests__/index.manually-hoisted.cjs jest.mock('../lib', () => ({ businessMessage: jest.fn(() => 'mocked!'), })); const { businessMessage } = require('../lib'); test('should use the mocked implementation', () => { expect(businessMessage()).toBe('mocked!'); });
-
jest.config.cjs: Configures Jest to pick up both
.jsand.cjstest files.// jest.config.cjs module.exports = { testMatch: [ '**/__tests__/**/*.js', '**/__tests__/**/*.cjs', ], };
- Jest's automatic hoisting of
jest.mockdoes not work in.cjsfiles, but works in.jsfiles. Manual hoisting (placingjest.mockbeforerequire) is required for.cjsfiles.
- Node.js version: v23.10.0
- npm version: 10.9.2
- npx version: 10.9.2
- Jest version: 29.7.0
- OS: macOS 15.5 (Darwin Kernel Version 24.5.0, arm64)
node --version
npm --version
npx --version
npx jest --version
uname -a
sw_versv23.10.0
10.9.2
10.9.2
29.7.0
Darwin LQ9357DK4K 24.5.0 Darwin Kernel Version 24.5.0: Tue Apr 22 19:53:27 PDT 2025; root:xnu-11417.121.6~2/RELEASE_ARM64_T6041 arm64
ProductName: macOS
ProductVersion: 15.5
BuildVersion: 24F74