javascript 为什么我运行这个测试时没有调用这个 sinon spy?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8441612/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why is this sinon spy not being called when I run this test?
提问by David Tuite
I have a Backbone Model:
我有一个主干模型:
class DateTimeSelector extends Backbone.Model
initialize: ->
@bind 'change:date', @updateDatetime
@bind 'change:time', @updateDatetime
updateDatetime: =>
# do some stuff with the sate and time
And I have some tests for that code using jasminand sinon.js
describe "DateTimeSelector", ->
beforeEach ->
@datetime = new DateTimeSelector()
describe "updateDatetime", ->
beforeEach ->
@updateSpy = sinon.spy(@datetime, 'updateDatetime')
afterEach ->
@datetime.updateDatetime.restore()
# passes
it "should be called when we call it", ->
@datetime.updateDatetime()
expect(@updateSpy).toHaveBeenCalledOnce()
# fails
it "should be called when we trigger it", ->
@datetime.trigger 'change:date'
expect(@updateSpy).toHaveBeenCalled()
# fails
it "should be called when we set the date", ->
@datetime.set { date: new Date() }
expect(@updateSpy).toHaveBeenCalled()
It seems to work when I use it in the browser but I can't seem to get the tests to pass. Can anyone enlighten me?
当我在浏览器中使用它时,它似乎可以工作,但我似乎无法通过测试。任何人都可以启发我吗?
回答by vadimich
duckyfuzz, you are experiencing this problem because when you are creating the spy (which actually wraps the original function and creates a level of indirection to insert its services of tracking method invocation) the binding of the events has already taken place. Which means that even though the spy wrapped the original function the event binding references the original function and not the wrapped spy. Hence, when you test, the original function gets executed on the event trigger but the spy tracking is one level above and is not executed.
duckyfuzz,您遇到此问题是因为当您创建 spy(它实际上包装了原始函数并创建了一个间接级别以插入其跟踪方法调用服务)时,事件的绑定已经发生。这意味着即使间谍包装了原始函数,事件绑定也引用了原始函数而不是包装的间谍。因此,当您测试时,原始函数会在事件触发器上执行,但间谍跟踪在上一级并且不会执行。
To make sure that the event binding is actually pointing to the wrapped spy function you have to create the spy before create the model object (same goes if you are testing views). To do that create the spy on the prototype."method" of the class:
为了确保事件绑定实际上指向包装的 spy 函数,您必须在创建模型对象之前创建 spy(如果您正在测试视图,也是如此)。为此,请在类的prototype."method"上创建间谍:
in the beforeEach ->section before @datetime = new DateTimeSelector()create the spy: @updateSpy = sinon.spy(DateTimeSelector.prototype, 'updateDatetime')
在@datetime = new DateTimeSelector()之前的beforeEach ->部分中创建间谍:@updateSpy = sinon.spy( DateTimeSelector.prototype, 'updateDatetime')
be sure to change your afterEach ->section where you return the prototype back to normal, like so: @updateSpy.restore()
请务必更改您的afterEach ->部分,您将原型恢复到正常状态,如下所示:@updateSpy.restore()
this should be your code:
这应该是你的代码:
describe "DateTimeSelector", ->
beforeEach ->
@updateSpy = sinon.spy(DateTimeSelector.prototype, 'updateDatetime')
@datetime = new DateTimeSelector()
afterEach ->
@updateSpy.restore()
# passes
it "should be called when we call it", ->
@datetime.updateDatetime()
expect(@updateSpy).toHaveBeenCalledOnce()
# should pass now
it "should be called when we trigger it", ->
@datetime.trigger 'change:date'
expect(@updateSpy).toHaveBeenCalled()
# should pass now
it "should be called when we set the date", ->
@datetime.set { date: new Date() }
expect(@updateSpy).toHaveBeenCalled()
BTW, if you are using jasmin-sinon.js plugin then your syntax is fine
顺便说一句,如果您使用的是 jasmin-sinon.js 插件,那么您的语法就很好
回答by Eric Bock
You're mixing the mocking syntax of jasmine and sinon together.
您将 jasmine 和 sinon 的模拟语法混合在一起。
In your passing test your sinon spy exposes the property calledOnce
but you're using a jasmine-esque function toHaveBeenCalledOnce()
. This function doesn't exist on the sinon spy so essentially no assert is taking place.
在您的通过测试中,您的 sinon 间谍公开了该属性,calledOnce
但您使用的是茉莉花式函数toHaveBeenCalledOnce()
。sinon spy 上不存在此功能,因此基本上没有发生断言。
In your failing tests you're calling the jasmine spy function toHaveBeenCalled()
on your sinon spy. Jasmine has its own syntax for creating a spy: spyOn(obj, 'method');
在你失败的测试中,你调用了toHaveBeenCalled()
sinon spy 上的 jasmine spy 函数。Jasmine 有自己的语法来创建间谍:spyOn(obj, 'method');