跳至主要内容
版本:29.7

与 webpack 一起使用

Jest 可用于使用 webpack 管理资产、样式和编译的项目。webpack 确实 提供了一些与其他工具相比的独特挑战,因为它直接与您的应用程序集成,允许管理样式表、图像和字体等资产,以及庞大的编译到 JavaScript 语言和工具生态系统。

webpack 示例

让我们从一个常见的 webpack 配置文件开始,并将其转换为 Jest 设置。

webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.jsx?$/,
exclude: ['node_modules'],
use: ['babel-loader'],
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
{
test: /\.gif$/,
type: 'asset/inline',
},
{
test: /\.(ttf|eot|svg)$/,
type: 'asset/resource',
},
],
},
resolve: {
alias: {
config$: './configs/app-config.js',
react: './vendor/react-master',
},
extensions: ['.js', '.jsx'],
modules: [
'node_modules',
'bower_components',
'shared',
'/shared/vendor/modules',
],
},
};

如果您有由 Babel 转换的 JavaScript 文件,您可以通过安装 babel-jest 插件来 启用对 Babel 的支持。非 Babel JavaScript 转换可以使用 Jest 的 transform 配置选项来处理。

处理静态资产

接下来,让我们配置 Jest 以优雅地处理样式表和图像等资产文件。通常,这些文件在测试中不太有用,因此我们可以安全地模拟它们。但是,如果您使用的是 CSS 模块,那么最好模拟一个代理来进行 className 查找。

jest.config.js
module.exports = {
moduleNameMapper: {
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
'<rootDir>/__mocks__/fileMock.js',
'\\.(css|less)$': '<rootDir>/__mocks__/styleMock.js',
},
};

以及模拟文件本身

__mocks__/styleMock.js
module.exports = {};
__mocks__/fileMock.js
module.exports = 'test-file-stub';

模拟 CSS 模块

您可以使用 ES6 代理 来模拟 CSS 模块

npm install --save-dev identity-obj-proxy

然后,您对样式对象的所有 className 查找将按原样返回(例如,styles.foobar === 'foobar')。这对 React 快照测试 非常有用。

jest.config.js(用于 CSS 模块)
module.exports = {
moduleNameMapper: {
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
'<rootDir>/__mocks__/fileMock.js',
'\\.(css|less)$': 'identity-obj-proxy',
},
};

如果 moduleNameMapper 无法满足您的要求,您可以使用 Jest 的 transform 配置选项来指定如何转换资产。例如,一个返回文件基本名的转换器(这样 require('logo.jpg'); 返回 'logo')可以写成

fileTransformer.js
const path = require('path');

module.exports = {
process(sourceText, sourcePath, options) {
return {
code: `module.exports = ${JSON.stringify(path.basename(sourcePath))};`,
};
},
};
jest.config.js(用于自定义转换器和 CSS 模块)
module.exports = {
moduleNameMapper: {
'\\.(css|less)$': 'identity-obj-proxy',
},
transform: {
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
'<rootDir>/fileTransformer.js',
},
};

我们告诉 Jest 忽略与样式表或图像扩展名匹配的文件,而是要求我们的模拟文件。您可以调整正则表达式以匹配您的 webpack 配置处理的文件类型。

提示

请记住,如果您希望将它与其他代码预处理器一起使用,请明确包含默认的 babel-jest 转换器

"transform": {
"\\.[jt]sx?$": "babel-jest",
"\\.css$": "some-css-transformer",
}

配置 Jest 以查找我们的文件

现在 Jest 知道如何处理我们的文件,我们需要告诉它如何找到它们。对于 webpack 的 modulesextensions 选项,Jest 的 moduleDirectoriesmoduleFileExtensions 选项有直接的对应关系。

jest.config.js
module.exports = {
moduleFileExtensions: ['js', 'jsx'],
moduleDirectories: ['node_modules', 'bower_components', 'shared'],

moduleNameMapper: {
'\\.(css|less)$': '<rootDir>/__mocks__/styleMock.js',
'\\.(gif|ttf|eot|svg)$': '<rootDir>/__mocks__/fileMock.js',
},
};
注意

<rootDir> 是一个特殊标记,Jest 会用您的项目的根目录替换它。大多数情况下,这将是您的 package.json 所在的文件夹,除非您在配置中指定了自定义的 rootDir 选项。

类似地,Jest 中对应于 Webpack 的 resolve.roots(设置 NODE_PATH 的替代方法)的是 modulePaths

jest.config.js
module.exports = {
modulePaths: ['/shared/vendor/modules'],
moduleFileExtensions: ['js', 'jsx'],
moduleDirectories: ['node_modules', 'bower_components', 'shared'],
moduleNameMapper: {
'\\.(css|less)$': '<rootDir>/__mocks__/styleMock.js',
'\\.(gif|ttf|eot|svg)$': '<rootDir>/__mocks__/fileMock.js',
},
};

最后,我们必须处理 webpack 的 alias。为此,我们可以再次使用 moduleNameMapper 选项。

jest.config.js
module.exports = {
modulePaths: ['/shared/vendor/modules'],
moduleFileExtensions: ['js', 'jsx'],
moduleDirectories: ['node_modules', 'bower_components', 'shared'],

moduleNameMapper: {
'\\.(css|less)$': '<rootDir>/__mocks__/styleMock.js',
'\\.(gif|ttf|eot|svg)$': '<rootDir>/__mocks__/fileMock.js',

'^react(.*)$': '<rootDir>/vendor/react-master$1',
'^config$': '<rootDir>/configs/app-config.js',
},
};

就是这样!webpack 是一个复杂而灵活的工具,因此您可能需要进行一些调整以处理特定应用程序的需求。幸运的是,对于大多数项目来说,Jest 应该足够灵活,可以处理您的 webpack 配置。

提示

对于更复杂的 webpack 配置,您可能还想研究以下项目:babel-plugin-webpack-loaders

与 webpack 一起使用

除了安装前面提到的 babel-jest 之外,您还需要添加 @babel/preset-env,如下所示

npm install --save-dev @babel/preset-env

然后,您需要按如下方式配置 Babel

.babelrc
{
"presets": ["@babel/preset-env"]
}
提示

Jest 会缓存文件以加快测试执行速度。如果您更新了 .babelrc 并且 Jest 未按预期工作,请尝试通过运行 jest --clearCache 来清除缓存。

提示

如果您使用动态导入(import('some-file.js').then(module => ...)),则需要启用 dynamic-import-node 插件。

.babelrc
{
"presets": [["env", {"modules": false}]],

"plugins": ["syntax-dynamic-import"],

"env": {
"test": {
"plugins": ["dynamic-import-node"]
}
}
}

有关如何将 Jest 与 webpack 一起使用(使用 React)的示例,您可以查看 此处