如何在 React 和 Webpack 中使用 Jest

Posted

技术标签:

【中文标题】如何在 React 和 Webpack 中使用 Jest【英文标题】:How to use Jest with React and Webpack 【发布时间】:2017-03-30 09:36:05 【问题描述】:

我试图将 Jest 配置为与 React 和 Webpack 一起使用。由于我使用 Webpack 别名和 ES6 模块导出的方式,我在配置它时遇到了很大的问题。

由于没有其他问题对我有用,我想向您展示我做了什么才能将 Jest 与 ReactJs 和 Webpack 一起使用。

【问题讨论】:

【参考方案1】:

我的主要问题是我使用 ES6 导出我的模块,我需要一个预处理器来处理导入。

鉴于该基本组件:

import 'Incription.scss';

import React from 'react;
import InscriptionModal from './InscriptionModal';

class Inscription extends React.Component 
    constructor(props) 
        super(props)
    
    render() 
        return <InscriptionModal />;
    


export default Inscription;

测试如下:

import React from 'react';
import renderer from 'react-test-renderer';

import Inscription from './Inscription';

describe('Inscription', () => 
    it('renders correctly', () => 
        const tree = renderer.create(<Inscription />).toJSON();

        expect(tree).toMatchSnapshot();
    );
);

package.json 中没有配置,当我运行测试时,我总是以:

SyntaxError: Unexpected token .

基本上,我需要处理资产文件,为此,我需要使用 moduleNameMapper 更改我的 package.json jest 配置。:

"jest": 
    "moduleNameMapper": 
      "^.+\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/cfg/mocks/fileMock.js",
      "^.+\\.(css|scss)$": "<rootDir>/cfg/mocks/styleMock.js"
    

fileMock.js

module.exports = 'test-file-stub';

styleMock.js

module.exports = ;

下一个问题是 Jest 无法处理 ES6 的模块,所以我需要一个预处理器。确切的错误是:

Cannot find module './InscriptionModal' from 'Inscription.spec.js'

我发现了一个名为 jest-webpack-alias 的插件,它正在这样做,我再次更改了我的 package.json 的开玩笑配置:

"jest": 
    ...
    "transform": 
        "^.+\\.js$": "<rootDir>/cfg/preprocessor.js"
    ,
    "jest-webpack-alias": 
        "configFile": "cfg/jest.js"
    ,

我的 preprocessor.js 文件看起来像:

const babelJest = require('babel-jest');

require('babel-register');
const webpackAlias = require('jest-webpack-alias');

module.exports = 
  process: function (src, filename) 
    if (filename.indexOf('node_modules') === -1) 
      src = babelJest.process(src, filename);
      src = webpackAlias.process(src, filename);
    
    return src;
  
;

注意我的 package.json 中 jest-webpack-file 的 configFile。它有我的 webpack 测试配置的路线。该文件如下所示:

'use strict';

const path = require('path');

const srcPath = path.join(__dirname, '/../src/');
const baseConfig = require('./base');

module.exports = 
  devtool: 'eval',
  module: 
    loaders: [
      test: /\.(png|jpg|gif|woff|woff2|css|sass|scss|less|styl)$/,
      loader: 'null-loader'
    , 
      test: /\.(js|jsx)$/,
      loader: 'babel-loader',
      include: [].concat(
        baseConfig.additionalPaths,
        [
          path.join(__dirname, '/../src'),
          path.join(__dirname, '/../test')
        ]
      )
    , 
      test: /\.json$/,
      loader: 'json-loader'
    ]
  ,
  resolve: 
    root: path.resolve(__dirname, '/../src'),
    extensions: [
      '',
      '.js',
      '.jsx'
    ],
    alias: 
      actions: `$srcPath/actions/`,
      components: `$srcPath/components/`,
      sources: `$srcPath/sources/`,
      stores: `$srcPath/stores/`,
      services: `$srcPath/services/`,
      styles: `$srcPath/styles/`,
      i18n: `$srcPath/i18n/`,
      config: `$srcPath/config/test`,
      utils: `$srcPath/utils/`,
      vendor: `$srcPath/vendor/`,
      images: `$srcPath/images/`
    
  
;

在此文件中添加项目的根目录非常重要,因为如果不添加,您将遇到此错误:

Missing setting "resolve.modules" (webpack v2) or "resolve.root" (webpack v1) in...

添加配置后,您现在可以使用 Jest mock 模拟您的导入:

jest.mock('./InscriptionModal, () => 
  return ;
);

在运行测试时添加参数--no-cache 很重要,因为 Jest 会缓存转换后的模块文件以加快测试执行速度。

另一个烦人的错误是当您尝试在测试中添加enzyme 或React Test Utils 时。它打印此错误:

Invariant Violation: ReactCompositeComponent: injectEnvironment() can only be called once.

你have to do 是在你的测试中添加这行代码:

jest.mock('react/lib/ReactDefaultInjection');

希望对你有用!

更新

UpgradingReact 和 React-dom 到 v15.4.0 修复了最新的错误评论。

【讨论】:

以上是关于如何在 React 和 Webpack 中使用 Jest的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 React + ES6 + webpack 导入和导出组件?

如何使用 React + Webpack 应用程序存储和访问我的 API 密钥?

如何使用 React 和 Webpack 设置 Babel 6 阶段 0

使用 React Router 和 Webpack 2 如何仅在某些路由上需要外部库?

如何使用 React、Redux 和 Webpack 实现 Google API

如何使用 Typescript、React 和 Webpack 导入 SCSS 或 CSS 模块