在没有 babel 的情况下存根从原生 ES 模块导出
Stub an export from a native ES Module without babel
我正在使用 AVA + sinon 构建我的单元测试。因为我需要 ES6 模块而且我不喜欢 babel,所以我在整个项目中都使用了 mjs 文件,包括测试文件。我使用“--experimental-modules”参数来启动我的项目,并在测试中使用 "esm" 包。以下是我的ava配置和测试代码
"ava": {
"require": [
"esm"
],
"babel": false,
"extensions": [
"mjs"
]
},
// test.mjs
import test from 'ava';
import sinon from 'sinon';
import { receiver } from '../src/receiver';
import * as factory from '../src/factory';
test('pipeline get called', async t => {
const stub_factory = sinon.stub(factory, 'backbone_factory');
t.pass();
});
但我收到错误消息:
TypeError {
message: 'ES Modules cannot be stubbed',
}
如何在没有 babel 的情况下存根 ES6 模块?
According to John-David Dalton, the creator of the esm package,只能更改 *.js
个文件的命名空间 - *.mjs
个文件 已锁定 .
这意味着 Sinon(和所有其他软件)无法存根这些模块 - 正如错误消息所指出的那样。这里有两种方法可以解决此问题:
- 只需将文件的扩展名重命名为
.js
即可使导出可变。这是侵入性最小的,因为 mutableNamespace
选项默认为 on esm
。当然,这仅在您使用 esm
加载器时适用。
- 使用代理所有导入的专用模块加载器,并根据您的喜好替换它们。
选项 2 的技术堆栈无关术语是 link seam - essentially replacing Node's default module loader. Usually one could use Quibble, ESMock、proxyquire
或 rewire
,这意味着使用 Proxyquire 时上面的测试看起来像这样:
// assuming that `receiver` uses `factory` internally
// comment out the import - we'll use proxyquire
// import * as factory from '../src/factory';
// import { receiver } from '../src/receiver';
const factory = { backbone_factory: sinon.stub() };
const receiver = proxyquire('../src/receiver', { './factory' : factory });
修改 proxyquire 示例以使用 Quibble 或 ESMock(均原生支持 ESM)应该是微不足道的。
诗乃需要与时俱进,否则就会落伍(ESM is becoming defacto now with Node 12),因为它的许多局限性导致使用起来非常痛苦。
This article 提供了一个解决方法(实际上是 4 个,但我只发现 1 个是可以接受的)。就我而言,我直接从模块导出函数并收到此错误:ES Modules cannot be stubbed
export function abc() {
}
解决方案是将函数放入 class 并改为导出:
export class Utils {
abc() {
}
}
请注意,方法语法中的 function
关键字已删除。
Happy Coding - 希望 Sinon 长篇大论 运行,但它看起来不太好,因为它过于僵硬。
我正在使用 AVA + sinon 构建我的单元测试。因为我需要 ES6 模块而且我不喜欢 babel,所以我在整个项目中都使用了 mjs 文件,包括测试文件。我使用“--experimental-modules”参数来启动我的项目,并在测试中使用 "esm" 包。以下是我的ava配置和测试代码
"ava": {
"require": [
"esm"
],
"babel": false,
"extensions": [
"mjs"
]
},
// test.mjs
import test from 'ava';
import sinon from 'sinon';
import { receiver } from '../src/receiver';
import * as factory from '../src/factory';
test('pipeline get called', async t => {
const stub_factory = sinon.stub(factory, 'backbone_factory');
t.pass();
});
但我收到错误消息:
TypeError {
message: 'ES Modules cannot be stubbed',
}
如何在没有 babel 的情况下存根 ES6 模块?
According to John-David Dalton, the creator of the esm package,只能更改 *.js
个文件的命名空间 - *.mjs
个文件 已锁定 .
这意味着 Sinon(和所有其他软件)无法存根这些模块 - 正如错误消息所指出的那样。这里有两种方法可以解决此问题:
- 只需将文件的扩展名重命名为
.js
即可使导出可变。这是侵入性最小的,因为mutableNamespace
选项默认为 onesm
。当然,这仅在您使用esm
加载器时适用。 - 使用代理所有导入的专用模块加载器,并根据您的喜好替换它们。
选项 2 的技术堆栈无关术语是 link seam - essentially replacing Node's default module loader. Usually one could use Quibble, ESMock、proxyquire
或 rewire
,这意味着使用 Proxyquire 时上面的测试看起来像这样:
// assuming that `receiver` uses `factory` internally
// comment out the import - we'll use proxyquire
// import * as factory from '../src/factory';
// import { receiver } from '../src/receiver';
const factory = { backbone_factory: sinon.stub() };
const receiver = proxyquire('../src/receiver', { './factory' : factory });
修改 proxyquire 示例以使用 Quibble 或 ESMock(均原生支持 ESM)应该是微不足道的。
诗乃需要与时俱进,否则就会落伍(ESM is becoming defacto now with Node 12),因为它的许多局限性导致使用起来非常痛苦。
This article 提供了一个解决方法(实际上是 4 个,但我只发现 1 个是可以接受的)。就我而言,我直接从模块导出函数并收到此错误:ES Modules cannot be stubbed
export function abc() {
}
解决方案是将函数放入 class 并改为导出:
export class Utils {
abc() {
}
}
请注意,方法语法中的 function
关键字已删除。
Happy Coding - 希望 Sinon 长篇大论 运行,但它看起来不太好,因为它过于僵硬。