使用 Jest 和 Webpack 别名进行测试

我希望能够使用网络包别名解决导入时使用 jest,并最佳地参考 webpack.aliases,以避免重复。

开个玩笑:

  "jest": {
"modulePaths": ["src"],
"moduleDirectories": ["node_modules"],
"moduleNameMapper": {
"^@shared$": "<rootDir>/shared/",
"^@components$": "<rootDir>/shared/components/"
}
},

Webpack 别名:

exports.aliases = {
'@shared': path.resolve(paths.APP_DIR, 'shared'),
'@components': path.resolve(paths.APP_DIR, 'shared/components'),
};

进口:

import Ordinal from '@shared/utils/Ordinal.jsx';
import Avatar from '@components/common/Avatar.jsx';

由于某些原因,@会导致问题,所以当删除(在别名和导入中)时,它可以找到 shared,但是 components仍然无法解决。

 FAIL  src/shared/components/test/Test.spec.jsx
● Test suite failed to run


Cannot find module '@shared/utils/Ordinal.jsx' from 'Test.jsx'

我试过使用 玩笑,网络包,化名巴别尔插件模块解析器玩笑/网络包文档

62412 次浏览

FWIW, Try switching the alias order, keep the more specific up and less specific down, e.g.

"moduleNameMapper": {
"^@components$": "<rootDir>/shared/components/",
"^@shared$": "<rootDir>/shared/"
}

Since I had the same problem before I read again, and this time more carefully the documentation. Correct config should be:

  "jest": {
"moduleNameMapper": {
"^@shared(.*)$": "<rootDir>/shared$1",
"^@components(.*)$": "<rootDir>/shared/components$1"
}
},

This seems to have been fixed.

Below is a working setup:

Versions

"jest": "~20.0.4"

"webpack": "^3.5.6"

package.json

"jest": {
"moduleNameMapper": {
"^@root(.*)$": "<rootDir>/src$1",
"^@components(.*)$": "<rootDir>/src/components$1",
}
}

webpack.shared.js

const paths = {
APP_DIR: path.resolve(__dirname, '..', 'src'),
};


exports.resolveRoot = [paths.APP_DIR, 'node_modules'];


exports.aliases = {
'@root': path.resolve(paths.APP_DIR, ''),
'@components': path.resolve(paths.APP_DIR, 'components'),
};

None of the suggested answers worked for me.

Was able to solve it with the following pattern:

Jest version 25+

moduleNameMapper: {
'^Screens(.*)': '<rootDir>/src/screens/$1',
'^Components(.*)': '<rootDir>/src/components/$1',
'^Assets(.*)': '<rootDir>/src/assets/$1',
'^Services/(.*)': '<rootDir>/src/services/$1',
},

this solution works well for me:

moduleNameMapper: {
'^Screens(.*)': '<rootDir>/src/screens/$1',
'^Components(.*)': '<rootDir>/src/components/$1',
'^Assets(.*)': '<rootDir>/src/assets/$1',
'^Services/(.*)': '<rootDir>/src/services/$1',
},

This is a real insanity but when I try to map module in package.json like this:

"jest": {
"moduleNameMapper": {
'@root/(.*)': '<rootDir>/../$1'
}
}

It doesn't work.

But when I do the same in jest.config.js it works:

module.exports = {
moduleNameMapper: {
'@root/(.*)': '<rootDir>/../$1'
}
}

Using: "jest": "^26.5.3", and "webpack": "4.41.5", I was able to properly match my webpack/typescript aliases in the jest.config.js with this pattern:

Webpack config:

module.exports = {
// the rest of your config
resolve: {
alias: {
'components': path.resolve(__dirname, 'js/app/components'),
'modules': path.resolve(__dirname, 'js/app/modules'),
'types': path.resolve(__dirname, 'js/types'),
'hooks': path.resolve(__dirname, 'js/app/hooks'),
'reducers': path.resolve(__dirname, 'js/app/reducers'),
'__test-utils__': path.resolve(__dirname, 'js/app/__test-utils__')
}
},
}

Jest.config.js:

  moduleNameMapper: {
'^types/(.*)$':  '<rootDir>/js/types/$1',
'^components/(.*)$': '<rootDir>/js/app/components/$1',
'^modules/(.*)$':  '<rootDir>/js/app/modules/$1',
'^hooks/(.*)$':  '<rootDir>/js/app/hooks/$1',
'^reducers/(.*)$':  '<rootDir>/js/app/reducers/$1',
'^__test-utils__/(.)$': '<rootDir>/js/app/__test-utils__/$1'
}

Here's an explanation of the symbols:

  • (.*)$: capture whatever comes after the exact match (the directory)
  • $1: map it to this value in the directory I specify.

and tsconfig.json:

    "paths": {
"config": ["config/dev", "config/production"],
"components/*": ["js/app/components/*"],
"modules/*": ["js/app/modules/*"],
"types/*": ["js/types/*"],
"hooks/*": ["js/app/hooks/*"],
"reducers/*": ["js/app/reducers/*"],
"__test-utils__/*": ["js/app/__test-utils__/*"]
}

For anyone using @ as the root of their modules, you have to be more specific since other libs can use the @ in node modules.

  moduleNameMapper: {
"^@/(.*)$": "<rootDir>/src/$1"
},

It translates to "anything that matches @/ should be sent to <rootDir>/src/<rest of the path>

Assume your webpack aliases lies in webpack.yml in "resolved_paths" block.

To add same aliases in jest, if your jest config is in package.json, use moduleDirectories:

"jest":{
"moduleDirectories":[
".",
"<rootDir>/shared/components/",
"<rootDir>/shared/",
"node_modules"
]
}