为什么相同的Mocha测试在第一次测试后失败?

时间:2013-05-21 21:41:41

标签: javascript testing coffeescript bind mocha

我有一个类MyClass,它接受​​作为方法附加到它的对象。这些方法调用MyClass.push将数据添加到对象的内部@_list数组中。两个完全相同的测试用例中的第二个失败了,但我不明白为什么:

chai = require "chai"
chai.should()

obj =
  name: 'foo'
  f: ->
    for i in [1..5]
      @push "Element #{i}"


class MyClass
  constructor: (@options) ->
    @methods = {}
    @_list = []

    if 'attach' of @options
      @attach @options.attach

  push: (m) ->
    @_list.push m

  list: ->
    @_list

  method: (v) ->
    @methods[v].f

  run: (options) ->
    @method('foo')()

  attach: (o) ->
    @methods[o.name] = o
    @methods[o.name].f = o.f.bind(@)

describe 'MyClass', ->
  it 'list should have five elements', ->
    v = new MyClass attach: obj
    v.run()
    v.list().length.should.equal 5
  it 'list should have five elements (#2)', ->
    v = new MyClass attach: obj
    v.run()
    v.list().length.should.equal 5

我认为它与函数绑定有关,因为当我用第二个v = new MyClass attach: obj替换:

v = new MyClass attach:
  name: 'foo'
  f: ->
    for i in [1..5]
      @push "Element #{i}"
两个测试都通过了。但我不明白这种行为,因为我认为.bind()创建了该函数的副本。那么这里发生了什么,以及如何让两个测试独立运行?

1 个答案:

答案 0 :(得分:1)

JavaScript(以及coffeescript)对象通过引用传递。当您开始第二次测试时,您的obj对象已更改,因为您通过执行以下操作修改了其f属性:

@methods[o.name].f = o.f.bind(@)

您可以传递它的副本以避免这种情况。