我使用以下构造作为Mock对象,该对象充当具有可链接方法的对象:
PlayerNull =
find : ->
populate : ->
exec : (callback) ->
callback false, false
在我的测试中,我将真实模型替换为此Mock对象,我的控制器依次调用每个函数,如:
Model.find().populate().exec(callback)
当我发现自己多次使用时,我很好奇是否可以使用以下形式的辅助函数创建辅助函数来简化(略微):
PlayerNull = helper.mockNest ['find', 'populate', 'exec'], (callback) ->
callback false, false
我来了以下功能代码,但这不起作用:
exports.mockNest = (func_names, func_final) ->
func_names.reverse()
func_next = func_final
for func_name in func_names
_func_next = func_next.bind({})
_next = {}
_next[func_name] = ->
_func_next
func_next = _func_next
func_next
我已经意识到我需要克隆func_next
每个循环,否则引用似乎得到维护,并且分配给func_next
似乎只是改变了以前的所有赋值。
答案 0 :(得分:2)
是的,您已正确识别问题,未能保留引用,这是典型的closure in a loop问题。
但是,克隆这个功能在这里确实没有帮助,你的实际问题是
_next[func_name] = -> _func_next
在_func_next
变量上创建一个闭包,在每次循环迭代中都会对其进行修改。
应该是
exports.mockNest = (func_names, func_final) ->
func_names.reverse()
func_next = func_final
for func_name in func_names
next = {}
next[func_name] = func_next
func_next = do (_next = next) ->
() ->
_next
func_next
答案 1 :(得分:0)
感谢Bergi的解释,我找到了以下解决方案:
exports.mockNest = (func_names, func_final) ->
# Assign the last function to the provided func_final
func_name_final = func_names.pop()
func_next = {}
func_next[func_name_final] = func_final
# Reverse the array so we build the object from last to first.
func_names.reverse()
for func_name in func_names
ignore = do (func_name, _func_next = func_next) ->
func_next = {}
func_next[func_name] = ->
_func_next
return
func_next
为了解释这些变化,我需要保留提供的func_final,所以我必须在循环之前分配。
此外,我需要将do
块分配给变量ignore
,否则Coffeescript会将该函数编译到不同位置,其中对func_next
所做的更改是无序的。分配可确保放置do
块。