gpt4 book ai didi

javascript - 使用 Rollup.js 时如何在 Jest 测试中正确模拟函数

转载 作者:行者123 更新时间:2023-12-05 04:40:54 27 4
gpt4 key购买 nike

我正在编写一个 React 库 MyLibrary 并将其与 Rollup.js 捆绑在一起2.58.3。我用 jest用于单元测试。

问题的快速总结

我无法使用 jest 从我的库中模拟模块。这是由于汇总“编译”我的代码的方式。

Rollup 使用其代码拆分功能来创建许多 block 。在一个示例中,汇总将 Alpha.js 分成两个 block :Alpha.jsAlpha-xxxxxx.js。原始文件中的一些功能被提取到这个“中间” block (Alpha-xxxxxx.js)。

在我的单元测试中,当模拟任何移入中间文件 Alpha-xxxxxx.js 的方法时,jest 似乎实际上是从这个“中间文件”加载模块"模块而不是顶层模块。

这会导致测试失败。

例如jest.mock('MyLibrary/dist/Alpha') 不起作用,因为模块实际上是从 Alpha-xxxxxx.js 而不是 Alpha.js 加载的

实例详细解释

我在 MyLibrary 中有两个模块 Alpha.jsBeta.js

MyLibrary/Alpha.js

export const Aaa = () => {
...
}
...

MyLibrary/Beta.js

import { Aaa } from './Alpha';
...
export const Bbb = () => {
...
}
...

rollup生成的编译输出

打包时,rollup.js 将 Alpha.js 分成 2 个 block Alpha.jsAlpha-xxxxxx.js。作为代码拆分的结果,Beta.js 的编译版本现在看起来像这样:

MyLibrary/dist/Beta.js

import { Aaa } from './Alpha-xxxxxx';
...
export const Bbb = () => {
...
}
...

这个来自 MyLibrary 的编译模块被导入到 MyApp 中,应用程序似乎正确导入它并且运行良好。

MyApp/index.js

import { Bbb } from 'MyLibrary/dist/Beta'
...

问题

下面的 jest 测试失败了,因为它没有正确模拟 Aaa 导出。

MyApp/index.test.js

import { Bbb } from 'MyLibrary/dist/Beta';

jest.mock('MyLibrary/dist/Alpha', () => ({
Aaa: jest.fn(),
}));

但是,如果我模拟 rollup 生成的中间 block ,它就可以工作。

import { stuff } from 'MyLibrary/dist/Beta';

jest.mock('MyLibrary/dist/Alpha-xxxxxx', () => ({
Aaa: jest.fn(),
}));

如何在我的 jest 测试中从我的库中正确模拟 Alpha

最佳答案

听起来您需要模拟一个模块,其文件名基础是确定的,但包含一个哈希后缀,该后缀随每次构建而变化。您还没有提供输出模块 block 文件名的完整模式,所以我将使用一个假设的例子:

假设您需要查找的 block 模块以这种模式发出:

Alpha-b38ca4f6.js

这意味着它是文字 Alpha- 后跟长度为 8 的字母数字哈希,然后是扩展名 .js

你可以用这个正则表达式表达:

^Alpha-[a-z0-9]{8}.js$

在将文件传递给 Jest 之前,您可以使用辅助函数找到正确的文件名。该函数应该接受一个目录和一个用于匹配文件模式的正则表达式。这是一个例子:

MyLibrary/utils.mjs:

import path from 'path';
import {promises as fs} from 'fs';

export async function findFileByPattern (dir, regex) {
const fileNames = (await fs.readdir(dir, {withFileTypes: true}))
.filter(entry => entry.isFile())
.map(entry => entry.name);

for (const fileName of fileNames) {
if (!regex.test(fileName)) continue;
const {name} = path.parse(fileName);
return path.join(dir, name);
}

throw new Error('File not found matching the provided pattern');
}

MyApp/index.test.js:

import { Bbb } from 'MyLibrary/dist/Beta';
import { findFileByPattern } from './utils';

const chunkFileName = await findFileByPattern('MyLibrary/dist', /^Alpha-[a-z0-9]{8}.js$/);

jest.mock(chunkFileName, () => ({
Aaa: jest.fn(),
}));

如果需要,您甚至可以使用该函数在构建后步骤中定位 block 文件名,并将值作为 JSON 工件发出:然后在测试中导入 JSON 并使用文件名值。这将允许您跳过每次运行测试时枚举 dist 目录的步骤。

关于javascript - 使用 Rollup.js 时如何在 Jest 测试中正确模拟函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70177334/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com