在学习Jasmine的过程中,我遇到了这个问题。我想要一个基本的函数来运行,然后设置一个超时来再次调用自己...简单的东西。
class @LoopObj
constructor: ->
loop: (interval) ->
#do some stuff
setTimeout((=>@loop(interval)), interval)
但我想测试以确保使用正确的args
调用setTimeoutdescribe "loop", ->
xit "does nifty things", ->
it "loops at a given interval", ->
my_nifty_loop = new LoopObj
interval = 10
spyOn(window, "setTimeout")
my_nifty_loop.loop(interval)
expect(setTimeout).toHaveBeenCalledWith((-> my_nifty_loop.loop(interval)), interval)
我收到此错误:Expected spy setTimeout to have been called with [ Function, 10 ] but was called with [ [ Function, 10 ] ]
这是因为(-> my_nifty_loop.loop(interval))
函数不等于(=>@loop(interval))
函数吗?或者它与第二个[ [ Function, 10 ] ]
周围的额外方括号有关?还有什么altogther?
我哪里出错?
答案 0 :(得分:1)
我不太了解CoffeeScript,但您可以通过替换
进行调试expect(setTimeout).toHaveBeenCalledWith((-> my_nifty_loop.loop(interval)), interval)
带
expect(setTimeout).toHaveBeenCalledWith(jasmine.any(Function), interval)
并重新运行规范。我想如果额外的方括号消失了,那么你的问题是因为你有两个不同的函数引用。如果它们没有消失,你的LoopObj定义会有一些奇怪的东西,可能是胖箭头操作符(看起来我的n00b眼睛不需要)。
答案 1 :(得分:1)
使用bind
辅助功能。
比较setTimeout的参数时遇到问题的原因是因为它隐藏在lambda中。你创造的每一个lambda都是不同的。在这种情况下,除了将函数绑定到this
的正确值之外,lambda实际上没有添加任何值。
事实证明,这是JavaScript中的常见模式,而Underscore.js库有一个名为bind
的函数,它正是这样做的。
通过分解这个模式并用setTimeout
(与_.delay
相同)来组合它,我们可以比较传递给它的参数,因为它们不会被包裹在lambda中。 / p>
window.bindAndDelay = (wait, fn, obj, args...) ->
setTimeout((-> obj.fn(args...)), wait)
class @LoopObj
constructor: ->
loop: (interval) ->
#do some stuff
bindAndDelay(interval, @loop, @, interval)
然后在你的测试中:
describe "loop", ->
xit "does nifty things", ->
it "loops at a given interval", ->
my_nifty_loop = new LoopObj
interval = 10
spyOn(window, "bindAndDelay")
my_nifty_loop.loop(interval)
expect(bindAndDelay).toHaveBeenCalledWith(interval, my_nifty_loop.loop, my_nifty_loop, interval)
我选择将延迟量作为bindAndDelay
的第一个参数,以便它适用于应用了任意数量参数的函数。
另一种方法是使用_.bindAll
,但你必须记住在每个对象上使用它,并且它不利于带参数的函数。所以我认为以上情况更好。
这应该有效,但我仍然认为它很臭。所以,如果其他人有更好的答案,请发帖!