在没有巴别塔的情况下从本机ES模块存根导出

人气:470 发布:2022-10-16 标签: node.js sinon ecmascript-6 es6-modules ava

问题描述

我正在使用AVA+SINON构建我的单元测试。因为我需要ES6模块,而我不喜欢巴别塔,所以我在我的项目中使用了mjs文件,包括测试文件。我在开始项目时使用的是"--实验性模块"参数,在测试中使用的是"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',
  }

如何在没有巴别塔的情况下为ES6模块添加存根?

推荐答案

According to John-David Dalton的创建者,只能更改*.js文件的命名空间-*.mjs文件被锁定。

这意味着SINON(和所有其他软件)不能存根这些模块--正如错误消息指出的那样。有两种方法可以解决此问题:

只需将文件的扩展名重命名为.js,即可更改导出。这是侵入性最小的,因为对于esm,默认情况下mutableNamespace选项为on。当然,这仅适用于使用esm加载器的情况。 使用专用的模块加载器,该加载器可以代理所有导入并根据您的喜好替换它们。 选项2的技术堆栈不可知术语是link seam--本质上取代了Node的默认模块加载器。通常可以使用Quibble、ESMock、proxyquirerewire,这意味着当使用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示例修改为使用Qubble或ESMock(两者本身都支持ESM)应该很简单。

215