【问题标题】:Stub an export from a native ES Module without babel从没有 babel 的 ES6 模块中存根函数
【发布时间】:2018-11-18 16:09:15
【问题描述】:

我正在使用 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 模块进行存根?

【问题讨论】:

    标签: sinon es6-modules ava


    【解决方案1】:

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

    这意味着 Sinon(和所有其他软件)无法存根这些模块 - 正如错误消息所指出的那样。您可以尝试使用link seam,使用proxyquirerewire,这意味着上面的测试将是这样的:

    // 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 });
    

    由于上述原因,我不能 100% 确定这是否有效,但值得一试。


    旧答案 - 仅适用于 *.js 文件(不适用于 *.mjs)。

    您需要将一个选项传递给esm,这将允许您拥有可变的命名空间。 ES模块默认是不可变的,也就是说Sinon不能做zilch。

    名为cjs.mutableNamespace 的选项在README 中进行了描述,它将修改Node 的运行时以允许您更改导出。

    如何启用该选项取决于您加载 esm 的方式,但自述文件显示:// Set options as a parameter, environment variable, or rc file.

    由于您不自己加载模块,我假设环境变量或 rc 文件是您仅有的两个选择。在 env 变量中填充 json 可能会很麻烦,所以我建议在名为 .esmrc.json 的文件中填充以下内容:

    {
      "cjs": { 
        "mutableNamespace": "true"
      }
    }
    

    我自己从未将选项传递给esm,所以不知道它是否未经修改就可以运行,并且上面的代码不能单独运行,这意味着我无法根据您的情况对其进行测试,但是我觉得应该很对。

    编辑:mutableNamespace 选项是默认选项,因此无需指定。

    【讨论】:

    • 仍然得到'ES Modules cannot be stubbed'。我可以制作一个可运行的项目。但是我怎样才能把项目发给你呢?
    • @JimJin 创建一个公共 github 存储库。如果您制作绝对 minimal 项目(例如,只包含一个要导入的文件和一个测试文件),我只需要克隆它。一个示例仓库:github.com/fatso83/sinon-1711-babel
    • @JimJin 我刚刚意识到您选择不填写Sinon 的错误报告模板。那很不幸,因为这意味着我不知道您使用的是哪个版本的诗农。到目前为止,我一直认为您使用的是绝对最新版本,但您似乎使用的是旧版本?直到 Sinon 5.0.8PR 1803 中才添加对使用上述选项的存根 ESM 模块的支持。
    • 我用的是最新的sinon。我会尽快创建回购。
    • 我无法通过点击投票来更改号码。真可惜。
    【解决方案2】:

    Sinon 需要与时俱进,否则就会被抛在后面 (ESM is becoming defacto now with Node 12),因为它有很多限制,使用起来非常痛苦。

    This article 提供了一种解决方法(实际上是 4,但我只发现 1 可以接受)。就我而言,我直接从模块中导出函数并收到此错误:ES Modules cannot be stubbed

    export function abc() {
    
    }
    

    解决方案是将函数放入一个类并导出:

    export class Utils {
      abc() {
      
      }
    }
    

    注意function 关键字在方法语法中被删除。

    Happy Coding - 希望诗乃能长期发展,但由于过于僵化,它看起来并不好。

    【讨论】:

      猜你喜欢
      • 2018-03-20
      • 2017-01-15
      • 2015-10-23
      • 2015-09-13
      • 2020-06-07
      • 2019-04-14
      • 2017-03-13
      • 1970-01-01
      • 2017-07-02
      相关资源
      最近更新 更多