jest: moduleNameMapper - mocks do not work for imported modules of mapped modules using "moduleNameMapper"
I use jest with webpack. Webpack is configured to use alias for some imports:
alias: {
shared: path.resolve(process.cwd(), "some-lib/src"),
},
modules: ["app", "node_modules", "some-lib"],
some-lib
is git submodule added to the project.
part of Jest config from package.json
:
"moduleDirectories": [
"node_modules",
"app",
"shared-lib"
],
"modulePaths": ["<rootDir>/shared-lib"],
"moduleNameMapper": {
"^api(.*)$": "<rootDir>/shared-lib/src$1"
},
When I’m trying to mock imported module in jest it doesn’t work
jest.mock("shared/utils")
import { utilFunc } from "shared/utils"
as a result utilFunc
is unmocked.
I’m using the latest version of jest.
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Reactions: 53
- Comments: 30 (7 by maintainers)
I have to confirm that currently Jest has serious issues with aliases defined in a webpack config:
jest.mock('aliased/module')
- doesn’t do automockingjest.genMockFromModule('aliased/module')
- cannot find the moduleThis issue is 1.5 years old. Will it be ever fixed?
I think “it works” but it’s broken maybe?
Example 1: it works
Module with something to mock
Test
Example 2: doesn’t work
Module with something to mock
Test
I can try to tackle this one.
Hello everyone, I just ran into this issue today. Is there anything I can do to help push this issue forward?
I’ve made a minimal example repo where the ModuleNameMapper does not resolve correctly for imports. https://github.com/Kruptein/jest-test-stuff
Running ‘npm run test’ results in: Track.test has behaviour I expect but uses relative imports, whereas the TrackExpected.test is the behaviour with mapped names with wrong behaviour.
Additionally this output shows that something does not seem to resolve correctly:
Does anyone have any new information about this, or know whether it’s going to be fixed before the next release? The same problem occurs when using a custom resolver. We use aliases/nonrelative paths almost exclusively so this is a big issue for us adopting jest. As of
23.0.0-charlie.2
it’s still not working for me.jest.mock('some/module')
is able to resolve the module (e.g. does not throw an error) but it doesn’t get automocked; the original is still used. Using an inline mock works, e.g.I’ve tried to reproduce it in isolation but haven’t been able to yet, using both relative & aliased/rooted paths for the original import. So it’s doesn’t seem like it’s quite as simple as how @alex-mironov initially observed it, or maybe it manifests differently for when using a custom resolver?
Additional info:
After a bit of tracing I think this is a result of circular dependencies, which while probably not good are valid in ES6 modules. If I can repro in isolation will file a specific issue.
We’re hitting this issue as well - upgrading to 22.2.2 or downgrading to 20.0.4 didn’t work.
Some details:
jest.mock()
jest-runtime.requireMock()
. Specifically:manualMock
gets set to null, which eventually callsthis._generateMock(from, moduleName);
manualMock
gets set to the absolute FS path (even though this isn’t a manual mock). This causes_generateMock
to not be called.manualMock
is a string/path, and in other cases (insideif (fs.existsSync(potentialManualMock))
) it’s a boolean with the path inmodulePath
.Unfortunately, that’s as far as I got. I attempted a fix but since I’ve only started working with this framework every change I made broke a bunch of tests…
Hopefully this helps someone find the true fix. I’m also happy to help put in a PR with some direction on what the fix should be.
is there any solution for this issue
Jest does not support webpack aliases - you need to use
moduleNameMapper
(which is what this issue is about).That said, I dug into this a tiny bit, and I’m not sure why it fail 😅 However, I’ve put together a failing integration test based on @Kruptein’s excellent reproduction (removing typescript and logging), so maybe it will lower the barrier for people wanting to send a PR to fix this 🙂 Please see #7668
You’re completely correct of course - I write almost exclusively ES201?/TypeScript these days and when I wrote that, in my mind, a module’s public API would always be well-defined 😉
I can take a shot for sure when I get a little free time.
Possible solution for some of you:
If it’s any help to anyone, I just got mine working with this:
In my file that is importing the module:
Then in my jest config:
And then you don’t call
jest.mock()
anywhere, you are basically just creating an alias for that import in the config and that’s it.For me, I am on latest versions of jest/ts-jest but when I call
jest.mock('mail/transactional-email')
it does not mock the module, it just fails silently and continues with tests, but the real module gets imported.To force jest to import the mock module I just mapped the module import path directly to the mocked module. Not exactly a great solution, but I wanted to share regardless if anyone is in a pinch.
To be honest, the docs for module mocking are really confusing in my opinion I think a big part of the issue here might just be outdated or difficult to understand documentation. My understanding here was that if you say to mock
src/modulename
then ANY import in the jest test environment should look for a mock file in a sibling directory of the imported module named__mocks__
and look formodulename
in there instead. Not sure if that is actually the case or not but would love someone to clarify.I hope this helps someone else! 🍻
I had experienced similar issues with jest v20.0.4 upgrading to v22.2.2 solved that issue.
If someone can find it interesting: in my case the problem was that the order of entries in
moduleNameMapper
was wrong… Children should always be before parents in that list.