doMock doesn't fake modules required from NodeJS Worker Thread
🐛 Bug Report
Module faked with jest.doMock would not be faked for code executed in NodeJS Worker Thread
To Reproduce
Steps to reproduce the behavior:
Main file index.js
const {Worker} = require('worker_threads')
// mocked module outside of Worker Thread. Mocked as expected
const foo = require('./foo')
module.exports = async () => {
return new Promise(resolve => {
const worker = new Worker('./worker.js')
const outOfWorkerFoo = foo()
worker.on('message', workerFoo =>
resolve({outOfWorkerFoo, workerFoo})
)
})
}
Worker code worker.js
const {parentPort} = require('worker_threads')
// mocked module inside of Worker Thread. Failed to be mocked
const foo = require('./foo')
parentPort.postMessage(foo())
The faked module. It's faked version would be executed for non-worker code and its real version would be executed for worker code
module.exports = () => 'real foo'
The test file index.test.js
const foo = jest.fn()
jest.doMock('./foo', () => foo)
const main = require('./index')
test('test', async () => {
foo.mockImplementation(() => 'mock foo')
const mockResult = await main()
expect(mockResult).toEqual({ // this check would failed
outOfWorkerFoo: 'mock foo', // value would be as expected: 'mock foo'
workerFoo: 'mock foo' // value would NOT be as expected: 'real foo'
})
})
Expected behavior
Faked scripts should be faked no matter whether they had been required inside of Worker Thread or not. And there should definitely never exist faked and real version of the same script at the same time
Link to repl or repo (highly encouraged)
https://github.com/Alexsey/jest-worker-threads-bug
envinfo
npx: installed 1 in 13.891s
System:
OS: Windows 10 10.0.18362
CPU: (4) x64 Intel(R) Core(TM) i5-6500 CPU @ 3.20GHz
Binaries:
Node: 13.7.0 - C:\Program Files\nodejs\node.EXE
npm: 6.13.6 - C:\Program Files\nodejs\npm.CMD
npmPackages:
jest: ^24.9.0 => 24.9.0
Thank you
Yeah, we don't support worker_threads (or child_process). Sorta related to #5274, but that issue is just about coverage, which would be solved at the same time.
I haven't spent much time digging into what we would need to change in order to support it...
@SimenB I have the same problem with moduleNameMapper - it does not apply to worker_threads. This issue needs to be reclassified, is not a bug report and it doesn't need repro - it is a feature request.
Isn't there some simple way to call jest from the worker thread to make it install its handlers? All that is needed is its require interceptor. This would be a very good temporary solution.
This issue is stale because it has been open for 1 year with no activity. Remove stale label or comment or this will be closed in 30 days.
Still relevant
I came up with this workaround - i'm able to get away with it because i'm doing more of an integration test where i'm using a test helper and loading it with worker_threads to reproduce a race condition, but hey, it might help someone:
in my test helper thread worker, at the top:
const mockedModules = new Map(
['dependency-1', 'dependency-2'].map((id) => [require.resolve(id), id]),
);
const originalJsHandler = require.extensions['.js'];
const hijackedExtensionHandler = (mod, filename) => {
const mockedModule = mockedModules.get(filename);
if (mockedModule) {
const mockId = `../__mocks__/${mockedModule}`;
filename = require.resolve(mockId);
}
return originalJsHandler(mod, filename);
};
require.extensions['.js'] = hijackedExtensionHandler;
This issue is stale because it has been open for 1 year with no activity. Remove stale label or comment or this will be closed in 30 days.
I don't think it has been resolved
This issue is stale because it has been open for 1 year with no activity. Remove stale label or comment or this will be closed in 30 days.
still relevant