I had some interesting tribulations in trying to test whether views were correctly bound to events. In backbone, we typically bind to events in the initialize method, using
I solved this problem by spying on a function called by my render function. So in your example:
myView = Backbone.View.extend({
initialize: function(){
_.bindAll(this, "render");
something.bind("change", this.render);
},
someOtherFunction: function(){}, //this function only called from render
render: function(){ this.someOtherFunction(); /* rest of render function */ }
});
test looks like:
this.myView = new MyView();
spyOn(this.myView, "someOtherFunction");
this.myView.something.trigger("change");
expect(this.myView.someOtherFunction).toHaveBeenCalled();
then I wrote a separate test for whatever someOtherFunction does.
This may be too closely coupled with Backbone internals, but you can check the callback chain manually:
expect(this.legendView.groupData._callbacks['change']).toContain(this.myView.render)
I ran into the same problem and changed my Views code from:
this.model.on('change', this.render, this);
to:
this.model.on('change', function () {
this.render();
}, this);
And my jasmine tests worked as expected.
Instead of spying on the callback you might try spying on something.bind. Then test that bind was called w/ the appropriate arguments. This is working for me so far. I'm using sinon.js instead of jasmine's built-in spies. sinon.js makes it a bit easier to test for args passed to a method call in a stack of same method calls (eg a bunch of calls to bind in a view init). So I haven't tested this idea w/ jasmine alone but believe it should be possible.
spyOn(this.legendView.groupData, 'bind');
this.myView = new MyView();
expect(this.legendView.groupData.mostRecentCall.args).toEqual('change', this.myView.render); // example!! only works if testing a single call to bind or the last call in a series (ie mostRecentCall)
And w/ sinon.js
sinon.spy(this.legendView.groupData, 'bind');
this.myView = new MyView();
expect(this.legendView.groupData.bind.calledWith('change', this.myView.render); // works w/ any number of calls to bind
I have managed to achieve this using prototype patching. Before you create the instance of the view, spyOn the constructor's prototype.
spyOn(MyView.prototype, 'changeSelected');
var view = new MyView();
view.selectSomething();
expect(view.changeSelected).toHaveBeenCalled();
You should consider looking at Sinon.js. You could stub/mock the render() call and not even have to worry about 'someOtherFunction()'.