使用 Jest 和 Webpack 别名进行测试

Posted

技术标签:

【中文标题】使用 Jest 和 Webpack 别名进行测试【英文标题】:Testing with Jest and Webpack aliases 【发布时间】:2017-07-26 13:50:25 【问题描述】:

我希望能够在使用 jest 时使用 webpack 别名来解析导入,最好是引用 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'

我尝试过使用jest-webpack-alias、babel-plugin-module-resolver 和Jest/Webpack docs

【问题讨论】:

因为你使用 webpack-2 你在 env:test 中使用transform-es2015-modules-commonjs 吗?见:using-with-webpack-2 ***.com/questions/33190795/…的可能重复 @ 符号表示scoped package,通常在您的第三方包路径中搜索。 【参考方案1】:

假设您的 webpack 别名位于“resolved_pa​​ths”块中的 webpack.yml 中。

要在 jest 中添加相同的别名,如果您的 jest 配置在 package.json 中:

"jest":
  "moduleDirectories":
     ".",
      "<rootDir>/shared/components/",
      "<rootDir>/shared/",
      "node_modules"
  

【讨论】:

【参考方案2】:

对于任何使用@ 作为其模块的root 的人,您必须更加具体,因为其他库可以在节点模块中使用@

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

它翻译为“任何与@/匹配的东西都应该发送到&lt;rootDir&gt;/src/&lt;rest of the path&gt;

【讨论】:

【参考方案3】:

使用:"jest": "^26.5.3","webpack": "4.41.5", 我能够将jest.config.js 中的 webpack/typescript 别名与此模式正确匹配:

Webpack 配置:

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' 
  

下面是对符号的解释:

(.*)$:捕获完全匹配之后的任何内容(目录) $1:映射到我指定的目录中的这个值。

和 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__/*"]
    

【讨论】:

如果你确信你做的一切都是正确的,但 TS 仍然抱怨没有找到导入:友好提醒重新启动你的 TS 服务器。 这个答案值得更多的支持 =)【参考方案4】:

这真是太疯狂了,但是当我尝试像这样在 package.json 中映射模块时:

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

它不起作用。

但是当我在jest.config.js 中做同样的事情时,它会起作用:

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

【讨论】:

【参考方案5】:

这个解决方案对我很有效:

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

【讨论】:

【参考方案6】:

没有一个规定的答案对我有用。

能够使用以下模式解决:

Jest 版本 25+

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

【讨论】:

【参考方案7】:

这似乎已经解决了。

下面是一个工作设置:

版本

"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'),
;

【讨论】:

请注意,配置可能位于jest.config.js 我的问题似乎是moduleNameMapper 只适用于您的源代码,但不适用于您的包代码。如何解决 node_modules 中具有 @@@ 别名的一些包?比如包umi【参考方案8】:

因为我在再次阅读之前遇到了同样的问题,这次更仔细地阅读了文档。正确的配置应该是:

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

【讨论】:

我尝试实现此配置,但仍然遇到同样的问题。找不到导入的文件:Cannot find module '@shared/utils/Ordinal.jsx' from 'Test.jsx'. 我必须用"modulePaths": ["src"] 解决我的路径。那么是的,这个解决方案奏效了:"^Commons$": "./Commons" 我遇到了与 OP 相同的问题,@mayid 的解决方案最终为我解决了这个问题。 如果你像我一样是个新手,这个配置可以在你的package.json文件中找到【参考方案9】:

FWIW,尝试切换别名顺序,保持更具体的向上和不太具体的向下,例如

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

【讨论】:

结合leo的回答试过了,还是有同样的错误。 能不能把完整的代码分享给大家,最好是github? 不幸的是,它不是一个私有的公司存储库。 你能用最小可行的代码创建一个 git repo,这个问题可以重现吗? 我也收到了与作用域包相同的错误消息。我在 gist.github.com/batwicket/da72ffa7d5324d8f7c5eb11f0ba07fad 创建了一个非常小的项目。我尝试了别名方法..没有运气。我可能错过了一些简单的东西。任何帮助表示赞赏。

以上是关于使用 Jest 和 Webpack 别名进行测试的主要内容,如果未能解决你的问题,请参考以下文章

如何在 React 和 Webpack 中使用 Jest

我无法通过 symfony/webpack-encore 使用 Jest 和 Vuejs 运行测试

用Jest进行单元测试

Vue Jest 别名配置

在 Jest 测试中使用 Webpack 的 DefinePlugin 变量

为啥 Jest 抛出“无效的钩子调用”?