Jest · Unit tests that survive refactors
How does module resolution work in Jest?
Short answer
Jest uses its own resolver, not the TypeScript or bundler resolver. Aliases from tsconfig paths need moduleNameMapper, and non-JavaScript imports need explicit mapping or transforms.
An import that the bundler understands can still fail in Jest. TypeScript's paths setting only affects type checking; it does not rewrite runtime imports unless the compiled output does. Jest resolves each import through its own algorithm and its own cache, so aliases and asset imports must be configured for the test runtime.
export default {
moduleNameMapper: {
"^@/(.*)$": "<rootDir>/src/$1",
"\\.(css|less)$": "<rootDir>/test/styleMock.ts",
"\\.(png|jpg|svg)$": "<rootDir>/test/fileMock.ts",
},
};Common resolution failures
- A path alias works in the app but fails in Jest
- A CSS or image import throws a syntax error
- A package ships ESM and Jest tries to require it as CommonJS
- A symlinked workspace package resolves to the wrong copy
- A stale resolver cache keeps an old alias
For ESM-only packages, either transform them by adjusting transformIgnorePatterns or map them to a compatible build. For monorepo symlinks, moduleDirectories and modulePaths can help, but the cleanest fix is often to point the mapping at the source package explicitly.
tsconfig, the bundler and Jest guarantees that one of them will drift. A shared config or a small helper that reads the same aliases reduces that risk.Follow-ups you should expect
Interviewers use these to check whether the first answer was understanding or memorisation.
- 1Why do tsconfig paths not work in Jest automatically?
- 2How do you mock a CSS import?
- 3Why does an ESM-only package fail in Jest?
- 4What do you do when an alias works in the app but not in tests?
Say it in the interview
Jest resolves modules itself, so it does not see tsconfig paths or bundler aliases unless I map them with moduleNameMapper. I also map CSS and image imports to stubs, because Jest has no loader pipeline for them. ESM-only packages often need a transform or a different entry point. I keep aliases in one place so the app, TypeScript and Jest do not drift apart.
Use this as a model, not a script. Saying it in your own words is what makes it survive follow-up pressure.
Related questions
Reading is step one
Now say it out loud.
Understanding an answer and delivering it under pressure are different skills. Rehearse this topic in a live Jest mock interview and get scored feedback on depth, clarity and confidence.