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 是一种很好的测试实践 - 我认为在大多数情况下,在测试期间简单地将属性设置为某个值会有很长的路要走(?)
无论如何,如果存根是一个对象而不是一个函数,它会被视为一个属性描述符怎么办? 就像是:
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 的最新版本吗?
最新的支持sandboxes
和sinon.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')
抛出
最有用的评论
一个并不少见的用例是提供了 getter 但没有提供 setter,这使得属性只读,这对于生产代码来说可能是一个好主意,但会妨碍测试。 让 Sinon 支持 getter 和 setter 可以说明该用例。