如何将webpack的外部依赖传递给jest?

13

我在我的Grunt构建过程中使用了这个Webpack配置:

module.exports = {
options: {
    output: {
        path: path.resolve('../ui/static/js'),
        filename: '[name].js',
        chunkFilename: '[id].[name].js',
        libraryTarget: 'amd',
        library: '[name]'
    },

    externals: [
        'jquery',
        'lodash',
        'backbone',
        'backbone.layoutmanager',
        'moment',
        'spin',
        'lib/select2.min',
        'dispatcher'
    ],
    resolve: {
        root: path.resolve('../ui'),
        alias: {
            'jst': 'static/jst'
        }
    }

我们现在正在转向使用React,并且我需要在我的测试文件中导入一些包含这些依赖项的文件,但是Jest找不到它们:

我们现在正在转向使用React,并且我需要在我的测试文件中导入一些包含这些依赖项的文件,但是Jest找不到它们:

Cannot find module 'lib/select2.min' from 'helpers.js'
Cannot find module 'jst/templates_jst' from 'base-view.js

如何正确解决这个问题?


你尝试过使用安装文件导入这些包并附加到“global”吗? - hunterc
是的。它在我的模板上失败了,这些模板包含在webpack中,像这样: resolve: { root: path.resolve('../ui'), alias: { 'jst': 'static/jst' } } 我在jest上得到了这个错误: Cannot find module 'jst/templates_jst' from 'base-view.js' - lasfin
我可以通过将spin、jquery和backbone添加到“__mocks__”文件夹中来防止错误,但我不知道如何处理“jst/templates_jst”。 - lasfin
2
另一种可能性是使用虚拟模拟: jest.mock('jst/templates_jst', () => {}, {virtual: true}) - alony
4个回答

5
以下是使用 webpack@4.11.1jest@23.1.0 的有效方法。假设这是你的外部 webpack 配置:
externals: {
  react: {
    root: 'React',
    commonjs2: 'react',
    commonjs: 'react',
    amd: 'react',
  },
}

您需要在jest配置文件中将每个外部库映射到正确解析的位置,如下所示:
moduleNameMapper: {
  "^./react": path.resolve(__dirname, 'node_modules/react'),
}

在调试问题时,请确保检查您构建的组件文件的外观。您希望确保看到类似于以下内容的东西:
!function(e,t){if("object"==typeof exports&&"object"==typeof module)
module.exports=t(require("react"));
else if("function"==typeof define&&define.amd)define(["react"],t);
else{var n="object"==typeof exports?t(require("react")):t(e.React);

重要的部分是,react 用于commonjs和amd,而 React 用于浏览器。


3
您需要模拟外部库。
以jquery为例:
1.在__test__文件夹的同级目录下创建一个__mocks__文件夹。
2.在其中创建一个与依赖项同名的文件,例如jquery(jquery.js)。
3.在测试文件中,使用jest.mock函数引用模拟的外部依赖项:jest.mock('jquery')。
来自Jest文档: https://facebook.github.io/jest/docs/manual-mocks.html 希望这可以帮到您。

这样做能解决问题吗?如果我在测试中模拟React,那么它们将不再通过,因为我需要实际的React来渲染组件进行测试。 - Maciej Gurban
对于React来说,这当然没有帮助。在React作为外部库的情况下,你必须将其放在依赖项中。但是,对于一些不影响测试但仍需要安装才能解析导入和编译内容的外部包,这很有效。在这种情况下,模拟数据非常适用。 - Maksim Nesterenko

2

对于我的情况,使用__mocks__会有点啰嗦,但我使用了

jest.mock('myModule', () => {/* module impl */}, {virtual: true})

如果__mocks__这个建议对你来说太冗长了,可以查看这里的文档:这里。这个文档讲解了如何使用第三个参数创建虚拟模块的模拟 - 这些模块在系统中不存在。

这太棒了,我在我进行的任何网络搜索中都没有看到这个提到过,对于外部库来说这非常有效,我也不想在创建时过于冗长,谢谢。 - Breakpoint25
非常好的答案。我不知道有这个 {virtual: true}。它对我非常有效! - danivicario

0
你还可以使用moduleNameMapper,但只需使用jest-transform-stub进行桩数据处理,如果你不需要其功能。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接