Sinon: 监视 ESM 默认导出失败/莫名其妙地被阻止

创建于 2020-05-02  ·  21评论  ·  资料来源: sinonjs/sinon

描述错误
以前, import * as foo from 'someModule' + spy(foo, 'default')可以正常工作(甚至在此repo 的问题中作为解决方案列出); 但是,现在这被手动 throw明确阻止了。

预期行为
Sinon 监视默认导出。

上下文(请填写以下信息):

  • 库版本:9.0.2

附加上下文
我认为这是为了避免TypeError: Cannot assign to read only property

但是,这可以通过使用旧的 skool __defineGetter__来绕过

最有用的评论

@mroderick如果您不喜欢这些评论,请忽略它们。 主动删除有助于其他用户的评论根本没有帮助。 假设您删除评论,那么您最终只会有类似的用户来一次又一次地发表评论,这反过来最终会导致线程被锁定。

编辑:您还可以使用超级容易找到的“取消订阅”按钮。 :)

我是这个项目的维护者,并尝试阅读所有评论。

我不能忽略评论或取消订阅某个问题,因为人们决定不遵守规定的规则,忽略提供的指导并为了自己的目的劫持原始问题。 我有责任尝试以礼貌、委婉和有效的方式解决问题。 劫持问题使得支持社区变得比需要的更难。

请帮助我帮助你和社区的其他人。

所有21条评论

在那个老问题中实际上没有提到__defineGetter__ ,只是 Object.defineProperty,然后只处理转译的 Webpack 模块,而不是实际的 ECMAScript 模块。 不是说它不起作用,虽然😄

您能否发布一些直接的 vanilla javascript 示例,您可以在其中覆盖导入的 ES 模块的(非默认)导出? 你需要两个文件some-module.mjsfile-that-overwrites.mjs来测试这个,他们需要有 Node 的.mjs扩展来启用import语法。

这个测试套件记录了 Sinon 当前的行为。

仅供参考的存根不适用于[email protected]+此处

@fatso83那个老问题确实没有(但我没有说它有😜)。

我的意思是,Sinon 在检测 ESM 时会抛出错误,因为稍后代码Object.defineProperty(object, property, methodDesc)将失败并显示TypeError: Cannot assign to read only property 'default' 。 但是, __defineGetter__不会失败:

object.__defineGetter__(property, methodDesc.value);

Buuuut,当我尝试修改 Sinon 代码并运行它时,我在__defineGetter__上遇到了一个未定义的错误(也许是严格模式或其他什么?)。

所以我在想一种不同的方式,比如重新创建对象(使用新值)而不是覆盖它的属性。 更复杂,但至少是可行的。

仅供参考的存根不适用于[email protected]+此处

上一个工作版本 3.8.3 也有同样的问题

@zorji@aelbore :我不知道你为什么在这个帖子中发帖。 如果您要报告新问题,请创建一个单独的问题并按照正常的报告步骤(如何验证、实际代码、版本等)。 我们不支持 Typescript并且从来没有这么说过,虽然它当然应该可以工作,但细节将取决于您的编译步骤。

所以我在想一种不同的方式,比如重新创建对象(使用新值)而不是覆盖它的属性。 更复杂,但至少是可行的。

是吗? ES 模块是在运行时绑定的静态功能,AFAIK,您无法修改它。

导入的特征在文件中可用,它们是导出特征的只读视图。 您不能更改导入的变量,但您仍然可以修改类似于 const 的属性。 此外,这些功能作为实时绑定导入,这意味着即使您无法像 const 那样修改绑定,它们的值也可以更改。

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules

期待看到您是否可以通过它到达任何地方,但如果您(或任何人!)做到了,我会感到惊讶。

此问题已自动标记为过时,因为它最近没有活动。 如果没有进一步的活动发生,它将被关闭。 感谢你的贡献。

糟糕的机器人。 这种蠢东西能不能关掉?

@OmgImAlexis你认为有什么理由让这个问题保持开放吗?

伙计们,请尽量保持问题的重点,只讨论原始帖子中提到的内容。

对于维护人员来说,花费我们无偿的空闲时间来支持免费软件,而不必在同一问题中导航正交主题,这已经足够具有挑战性了。

我们很高兴 Sinon(一种 JavaScript 工具)在 TypeScript 社区中也很有用。 但是,就像@fatso83所说的,我们不支持 Typescript

将删除此问题中有关 TypeScript 的任何其他偏离主题的评论。

将删除此问题中有关 TypeScript 的任何其他偏离主题的评论。

@mroderick如果您不喜欢这些评论,请忽略它们。 主动删除有助于其他用户的评论根本没有帮助。 假设您删除评论,那么您最终只会有类似的用户来一次又一次地发表评论,这反过来最终会导致线程被锁定。

编辑:您还可以使用超级容易找到的“取消订阅”按钮。 :)

抱歉,我工作太忙了。 我会试着在几周内看看。 有几个库实现了这一点,所以它一定是可能的 😁

@mroderick如果您不喜欢这些评论,请忽略它们。 主动删除有助于其他用户的评论根本没有帮助。 假设您删除评论,那么您最终只会有类似的用户来一次又一次地发表评论,这反过来最终会导致线程被锁定。

编辑:您还可以使用超级容易找到的“取消订阅”按钮。 :)

我是这个项目的维护者,并尝试阅读所有评论。

我不能忽略评论或取消订阅某个问题,因为人们决定不遵守规定的规则,忽略提供的指导并为了自己的目的劫持原始问题。 我有责任尝试以礼貌、委婉和有效的方式解决问题。 劫持问题使得支持社区变得比需要的更难。

请帮助我帮助你和社区的其他人。

此问题已自动标记为过时,因为它最近没有活动。 如果没有进一步的活动发生,它将被关闭。 感谢你的贡献。

糟糕的机器人。

@jshado1你认为这个问题应该保持开放吗?

我看到@jshado1说这曾经工作得很好,但我认为这在香草未转译的 javascript 中从来没有工作过。 因为它不应该。 它可以在使用 Babel/Webpack 或类似工具转译模块时工作,因为您只模拟模块,而不是在运行时实际创建只读对象(哪些模块是)。 throw 子句是我添加的,因为当您尝试更改不可更改的内容时,它会稍后抛出_。 不过,诸如esm类的运行时/模块加载器会稍微更改该字段。

如果您认为这种行为是错误的,我建议您只需编辑node_modules/sinon/lib/sinon/spy.js ,删除 throws 子句并返回报告。 别往心里放。 承诺:独角兽::彩虹:

引用@RyanCavanaugh (https://github.com/microsoft/TypeScript/issues/38568#issuecomment-628860591)

如果您的目标是commonjs但编写 ES 模块导入/导出,TS 仍会尝试为您提供 ES 模块行为。

这段代码实际上是不合法的 ES,因为它试图修改(间接通过sinon.stub )一个只读属性(用import * as name导入的东西的属性是不可变的)。 它不应该奏效。

这基本上就是我一直在说的。 所以结束,因为这的结果完全取决于您使用转译步骤,转译器如何执行该步骤等。如果它试图创建一个有点符合 ESM 规范的结果,_它不应该工作_作为ES 模块的导出是不可变的(当然不是这些导出绑定的实际对象)。

@mroderick @fatso83对不起,我从来没有休息过,从那以后一直在工作。 已经几个月了,但如果没记错的话,我当时有一个_非常_基本的(和肮脏的 AF)工作示例来确认它确实有效(但确实_可能_不应该)。 但是,我认为这不是要走的路,因为我相信有/将是通过 ems 加载器执行此操作的官方方法: https :

这些目前不稳定(明确表示很快会改变),所以可能会推迟,直到它们变得更加稳定。 但是一旦他们这样做了,我认为这就是要走的路。

更新:目前正在 nodejs/node#36396 中讨论。

我认为我在此评论中的建议会使这变得非常简单。 用户可以手动提供地图,esm 加载程序可以使用它来替代:

// const mocksMap = { 'serviceA.js': 'serviceA.mock.js' };

const mock = mocksMap[importPath]; // note: it's not called `importPath` in the loader hooks
if (mock) // …

和/或,esm 加载器可以根据文件名查找模拟匹配(quick ndirty 示例):

const ext = path.ext(importPath);
const filename = path.basename(importPath, ext);
const mockFile = await import(`${filename}.mock${ext}`);

if (mockFile) // …

@jshado1感谢您提供该链接。 链接的问题本质上是试图找到一种标准化的方法来处理在 _link level_ 上替换依赖项的问题,这类似于 rewire 和 proxyquire 等工具所做的事情(我们在主页上的此操作

此页面是否有帮助?
0 / 5 - 0 等级