Sinon: 包装 ES5 getter 和 setter

创建于 2012-03-03  ·  23评论  ·  资料来源: sinonjs/sinon

var o = {
  get foobar() { return 'foobar' },
  set foobar(s) { throw 'bzzt!' },
  foo: function() { return 'foo' },
  bar: 'bar'
}; // -> { foobar: [Getter/Setter], foo: [Function], bar: 'bar' }

sinon.mock(o).expects('foobar').returns('woohoo'); // doesn't because sinon.wrapMethod() does an object[property] which accesses the getter which returns a string

要支持 getter 和 setter,您需要为对象执行Object.getOwnPropertyDescriptor(obj, prop) ,然后递归Object.getPrototypeOf(obj)如果它不存在,则描述符具有'get''set'定义它们的属性。

但是,您可能只想模拟 getter 或 setter 或两者,那么如何指定呢? 一些选项:

mock(o).expects('foobar'); // ambiguous, the setter? getter? or both?
mock(o).expects('get foobar'); // ambiguous, there may be a legitimate property named "get foobar"
mock(o).expectsGet('foobar'); // clear but more code in Sinon and more to document ?
mock(o).expectsSet('foobar'); // ditto

而且,您是否已经制定了处理当前环境中可能不存在的功能的约定? 如果有人试图在 IE6 中执行此操作会发生什么?

最有用的评论

一个并不少见的用例是提供了 getter 但没有提供 setter,这使得属性只读,这对于生产代码来说可能是一个好主意,但会妨碍测试。 让 Sinon 支持 getter 和 setter 可以说明该用例。

所有23条评论

看看你的例子,我不完全确定模拟 getter 是一种很好的测试实践 - 我认为在大多数情况下,在测试期间简单地将属性设置为某个值会有很长的路要走(?)

无论如何,如果存根是一个对象而不是一个函数,它会被视为一个属性描述符怎么办? 就像是:

stub(o, "foobar", { get: function () { return 42; } });

我不确定如何解决您的期望。 但就像我说的 - 但是对财产查找提出模拟期望值值得吗? 在我看来,如果您需要,也许它们应该是“实际”方法?

这个例子很简单。 我试图执行此操作的真正代码称为get identifier ,它附加了一些东西,其中一些来自我不想在测试中打扰的地方,我只是想确认一下x.identifier被访问,然后控制返回的内容。 现在我要使用getIdentifier() ,这很好,但鉴于我们可能会在未来看到更多的 getter 和 setter 计算属性,这可能是 Sinon 可以/应该处理的事情吗?

这个还是有点犹豫不决让它休息一段时间,稍后再决定。 如果您有更多意见/建议,请随时在此处记下。

一个并不少见的用例是提供了 getter 但没有提供 setter,这使得属性只读,这对于生产代码来说可能是一个好主意,但会妨碍测试。 让 Sinon 支持 getter 和 setter 可以说明该用例。

就目前而言,我看不到在 Sinon 中支持 getter 和 setter 的价值。

显然,自从讨论这个问题已经有一段时间了,但是这个功能会非常有帮助......

+1
我也很怀念。 当与在某些底层资源(如文件或数据库对象)上作为 getter 抽象工作的组件一起使用时,它会特别有用。 能够存根那些 getter 会很好。

我也希望看到这个重新开放。 它特别适用于包装位置对象的存根字段。

+1 该功能!

:+1: 我也只是觉得需要这个功能。

:+1: 这需要重新打开。 特别是随着 ES6 的流行,这比以往任何时候都更加重要。 我喜欢expectsGet变体。

+1 我完全同意@simonzack

+1

我也希望看到这个重新开放。 它特别适用于包装位置对象的存根字段。

https://github.com/mroderick/wrapple是否为您填补了这个空白?

现在我非常广泛地使用 wrapple,我已经忘记了对这个问题发表评论。 这可能意味着 wrapple 已经像你所说的那样填补了空白。

+1 偶然发现 sinon 不支持 getter 嘲笑

@derwaldgeist ,您使用的是Sinon 的最新版本吗?

最新的支持sandboxessinon.stub存根 getter。

你所要做的就是使用get函数,例如:

var myObj = {
    prop: "foo"
};

createStub(myObj, "prop").get(function getterFn() {
    return "bar";
});

myObj.prop // "bar"

请让我知道这是否适合您的用例,或者您有任何进一步的疑问。

感谢您这么快回来,非常感谢。
但是,我没有找到如何恢复已定义的getter方式? 我什至查看了sinon的源代码,并没有看到调用get()时存储原始getter的机制。

@derwaldgeist

确实可以恢复 getter,即使它们在被存根之前是未定义的。 您要做的就是在创建的存根中调用restore方法,例如:

var myObj = {
    prop: "foo"
};

var stub = createStub(myObj, "prop");

stub.get(function getterFn() {
    return "baz";
});

myObj.prop // "baz"

stub.restore();

myObj.prop // "foo"

我们在stub方法本身(当存根非函数属性时)wrapMethod实用程序中添加此restore方法。

哇,这真快。 我试过这个:

 const stub = sinon.stub(myObj, 'prop');
 stub.get(() => ({}));
  ...
 stub.restore();

但是在执行 restore() 时它说: Cannot redefine property: prop

你的createStub方法来自哪里?

@derwaldgeist我是从测试中得到的,抱歉,忘了编辑它。 但无论如何,它与sinon.stub

你能告诉我你用的是什么版本的sinon以便我检查吗?

我认为您可能还没有使用最新版本,其中我们修复了一个错误,您无法恢复属性,因为属性是在没有configurable: true情况下定义的,因此我们无法更改它们的描述符。

我看到的和@derwaldgeist 一样。 我_认为_我正在使用 v4,但其他一些部门正在使用 v1.7,所以我不确定_实际上_正在使用哪个。 我没有看到sinon.version可以在运行时检查的地方。

@jshado1如果您想知道您使用的是哪个主要版本,可以参考更改日志或迁移指南并测试重大更改。 对于版本 4,您可以断言sinon.stub({}, 'nonExistingProperty')抛出

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

相关问题

fearphage picture fearphage  ·  3评论

zimtsui picture zimtsui  ·  3评论

kbirger picture kbirger  ·  3评论

kevinburkeshyp picture kevinburkeshyp  ·  4评论

ndhoule picture ndhoule  ·  4评论