I have a fairly straightforward set of specs for a backbone view:

describe 'Avia.MatricesView', ->

  beforeEach ->
    @model = {
      bind: ->
      fetch: ->
    }
    spyOn(Avia, 'Matrices').andReturn(@model)
    @matricesView = new Avia.AviaView(addFixtureDiv('fixture'))

  describe 'initialization', ->

    beforeEach ->
      spyOn(@model, 'bind')
      spyOn(@model, 'fetch')
      @matricesView.initialize()

    it 'creates a new Matrices model', ->
      expect(Avia.Matrices).toHaveBeenCalledOnce()

    it 'binds the model change event to render', ->
      expect(@model.bind).toHaveBeenCalledWith('change', @matricesView.render)

    it 'fetches the model data', ->
      expect(@model.fetch).toHaveBeenCalledWith(success: @matricesView.render, error: @matricesView.showError)

The MatricesView does just as the spec expects:

initialize: =>
  @model = new Avia.Matrices()
  @model.bind('change', @render)
  @model.fetch(success: @render, error: @showError)

showError: =>
  alert('An error occurred while fetching data from the server.')

render: =>
  html = JST['views/matrices_view_template']()
  @el.html(html)

The expectation that a new Matrices model is being created passes. The other two specs fail, though, in ways that confuse me:

Avia.MatricesView initialization binds the model change event to render. (/home/duncan/avia/spec/javascripts/views/matrices_view_spec.js.coffee:21)
  Expected spy bind to have been called with [ 'change', Function ] but was called with [ [ 'change', Function ] ] (line ~22)
    expect(this.model.bind).toHaveBeenCalledWith('change', this.matricesView.render);

Avia.MatricesView initialization fetches the model data. (/home/duncan/avia/spec/javascripts/views/matrices_view_spec.js.coffee:24)
  Expected spy fetch to have been called with [ { success : Function, error : undefined } ] but was called with [ [ { success : Function, error : Function } ] ] (line ~25)
    expect(this.model.fetch).toHaveBeenCalledWith({

As far as I can tell, Jasmine thinks that the function returned by @matricesView.render in the scope of the spec is different to the function returned by @render in the scope of the instance of the MatricesView.

Also, I completely fail to understand why @matricesView.showError is undefined when it's clearly defined in MatricesView.

Any help would be greatly appreciated. I definitely need a second pair of eyes on this as mine are a bit weary right now :-/

有帮助吗?

解决方案

Right, I'm really embarrassed now. Looking at this with a fresh pair of eyes in the morning:

@matricesView = new Avia.AviaView(addFixtureDiv('fixture')) 

... should have been ...

@matricesView = new Avia.MatricesView(addFixtureDiv('fixture')) 

The test should have been failing, as I was actually testing the wrong class.

o_O

其他提示

The first failed test seems to be related to this issue: https://github.com/pivotal/jasmine/issues/45 Try wrapping your arguments in an array:

expect(@model.bind).toHaveBeenCalledWith(['change', @matricesView.render])

The second one is more baffling—there's no way @matricesView.showError is undefined (and you could throw in a console.log to confirm this). So that's probably just a stringification problem; try producing a simplified test case and posting to the Jasmine issue tracker. But as far as getting the test to pass, try the array wrapping. If that doesn't work, could it be that Jasmine is testing for reference equality rather than deep object equality? If that's the case, you might want to try the recently-added objectContaining matcher.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top