如何在 webpack 中使用 jest?

IT技术 reactjs webpack jestjs
2021-04-20 17:53:27

我使用webpack开发了一个 React 组件。这是它的一个简单版本:

'use strict';

require('./MyComponent.less');

var React = require('react');

var MyComponent = React.createClass({
  render() {
    return (
      <div className="my-component">
        Hello World
      </div>
    );
  }
});

module.exports = MyComponent;

现在,我想使用jest测试这个组件这是我的相关部分package.json

"scripts": {
  "test": "jest"
},
"jest": {
  "rootDir": ".",
  "testDirectoryName": "tests",
  "scriptPreprocessor": "<rootDir>/node_modules/babel-jest",
  "unmockedModulePathPatterns": [
    "react"
  ]
}

运行时npm test,出现以下错误:

语法错误:/Users/mishamoroshko/react-component/src/tests/MyComponent.js:/Users/mishamoroshko/react-component/src/MyComponent.js:/Users/mishamoroshko/react-component/src/MyComponent.less:意外令牌非法

看起来 webpack 需要处理,require('./MyComponent.less')然后 jest 才能运行测试。

我想知道是否需要使用jest-webpack 之的东西如果是,有没有办法指定多个scriptPreprocessors?(请注意,我已经使用了babel-jest

6个回答

我发现忽略所需module的最干净的解决方案是使用moduleNameMapper 配置(适用于最新版本 0.9.2)

文档很难遵循。我希望以下内容会有所帮助。

将 moduleNameMapper 键添加到您的 packages.json 配置中。项目的键应该是所需字符串的正则表达式。'.less' 文件示例:

"moduleNameMapper": { "^.*[.](less|LESS)$": "EmptyModule" },

将 EmptyModule.js 添加到您的根文件夹中:

/**
 * @providesModule EmptyModule
 */
module.exports = '';

注释很重要,因为 moduleNameMapper 使用 EmptyModule 作为该module的别名(阅读更多关于 providesModule)。

现在,与正则表达式匹配的每个 require 引用都将被替换为空字符串。

如果将 moduleFileExtensions 配置与“js”文件一起使用,请确保还将 EmptyModule 添加到“unmockedModulePathPatterns”中。

这是我最终得到的笑话配置:

"jest": {
  "scriptPreprocessor": "<rootDir>/node_modules/babel-jest",
  "moduleFileExtensions": ["js", "json","jsx" ],
  "moduleNameMapper": {
    "^.*[.](jpg|JPG|gif|GIF|png|PNG|less|LESS|css|CSS)$": "EmptyModule"
  },
  "preprocessorIgnorePatterns": [ "/node_modules/" ],
  "unmockedModulePathPatterns": [
    "<rootDir>/node_modules/react",
    "<rootDir>/node_modules/react-dom",
    "<rootDir>/node_modules/react-addons-test-utils",
    "<rootDir>/EmptyModule.js"
  ]
}
确认这是有效的,只需确保EmptyModule.js在评论之前您没有任何内容(就像另一个评论一样)
2021-05-27 17:53:27
这也是 Facebook 的create-react-app使用的解决方案稍微修改了一下,但它是相同的技术。如果您npm run eject在一个新create-react-app项目中,您将能够非常清楚地看到实施
2021-05-29 17:53:27
那行得通,但是……它真的是最干净的解决方案吗?如果我们可以告诉 Jest 忽略某些文件而不必创建空module,那就太好了
2021-06-04 17:53:27
这似乎对我的没有任何影响。仍然得到同样的unexpected token .错误。
2021-06-09 17:53:27

我最终得到了以下黑客:

// package.json

"jest": {
  "scriptPreprocessor": "<rootDir>/jest-script-preprocessor",
  ...
}


// jest-script-preprocessor.js
var babelJest = require("babel-jest");

module.exports = {
  process: function(src, filename) {
    return babelJest.process(src, filename)
      .replace(/^require.*\.less.*;$/gm, '');
  }
};

但是,我仍然想知道这个问题的正确解决方案是什么。

modulePathIgnorePatterns不会在没有代码的情况下实现相同的效果吗?还有modulePaths,我可以将它与 webpack 别名一起使用。它还需要一个 simlink 来匹配别名。讨厌的黑客...
2021-05-28 17:53:27
不知道为什么它对我不起作用,仍然看到同样的错误:(
2021-05-30 17:53:27
jest.moduleNameMapper 与模拟文件是要走的路,记录在这里(除非你坚持使用旧版本的 Jest
2021-06-09 17:53:27
我还没有找到更好的解决方案?除非有人知道补丁。这样做我觉得很恶心:( - 唉,谢谢你的工作。
2021-06-17 17:53:27

我刚刚发现使用 Jest 的moduleNameMapper配置更简单

// package.json

"jest": {
    "moduleNameMapper": {
      "^.+\\.scss$": "<rootDir>/scripts/mocks/style-mock.js"
    }
}

// style-mock.js

module.exports = {};

更多细节在 Jest 的教程页面

现在这是最好的方法,今天您链接到的 Jest 文档非常清楚地解释了您需要做什么。我已经设法用它很快地设置好了,即使我的设置甚至包括 TypeScript。
2021-06-11 17:53:27

我最近发布了Jestpack,这可能会有所帮助。它首先使用 Webpack 构建您的测试文件,因此任何自定义module解析/加载程序/插件等都可以正常工作,您最终会使用 JavaScript。然后它为 Jest 提供了一个自定义module加载器,它了解 Webpack module运行时。

来自Jest 文档

// in terminal, add new dependency: identity-obj-proxy
npm install --save-dev identity-obj-proxy

// package.json (for CSS Modules)
{
  "jest": {
    "moduleNameMapper": {
      "\\.(css|less)$": "identity-obj-proxy"
    }
  }
}

上面的代码片段将所有.less文件路由到新的依赖项identity-obj-proxy,它会在调用时返回一个带有类名的字符串,例如'styleName'for styles.styleName