Reputation: 1006
I was trying to learn the ways of testing Backbone-based app using Jasmine. For this, I picked up some sample code from here: http://msdn.microsoft.com/en-us/scriptjunkie/hh377172.
Photo = new Backbone.Model.extend({
defaults:{
title: 'Another photo!',
tags: ['untagged'],
location: 'home',
src: 'placeholder.jpg'
},
initialize: function(){
console.log('this model has been initialized');
this.bind("change:title", function(){
var title = this.get("title");
console.log("My title has been changed to.." + title);
});
},
setTitle: function(newTitle){
this.set({ title: newTitle });
}
});
Then wrote the test spec as follows:
describe("Photo Model", function() {
it("verifies title", function() {
var myPhoto = new Photo();
myPhoto.set({ title: "On the beach" });
expect(myPhoto.get("title"))
.toEqual("On the beach");
});
});
While running it, the test fails with TypeError
TypeError: Object [object Object] has no method 'apply'
at new <anonymous> (http://localhost:88/backbone/WebClient-Backbone2/js/backbone.js:1103:41)
at [object Object].<anonymous> (http://localhost:88/backbone/WebClient-Backbone2/test/spec.js:28:16)
at [object Object].execute (http://localhost:88/backbone/WebClient-Backbone2/test/lib/jasmine/jasmine.js:1001:15)
at [object Object].next_ (http://localhost:88/backbone/WebClient-Backbone2/test/lib/jasmine/jasmine.js:1790:31)
at [object Object].start (http://localhost:88/backbone/WebClient-Backbone2/test/lib/jasmine/jasmine.js:1743:8)
at [object Object].execute (http://localhost:88/backbone/WebClient-Backbone2/test/lib/jasmine/jasmine.js:2070:14)
at [object Object].next_ (http://localhost:88/backbone/WebClient-Backbone2/test/lib/jasmine/jasmine.js:1790:31)
at [object Object].start (http://localhost:88/backbone/WebClient-Backbone2/test/lib/jasmine/jasmine.js:1743:8)
at [object Object].execute (http://localhost:88/backbone/WebClient-Backbone2/test/lib/jasmine/jasmine.js:2215:14)
at [object Object].next_ (http://localhost:88/backbone/WebClient-Backbone2/test/lib/jasmine/jasmine.js:1790:31)
Upvotes: 0
Views: 2944
Reputation: 1451
There is a good set of tutorials for testing a backbone based application with Jasmine here: http://tinnedfruit.com/2011/03/03/testing-backbone-apps-with-jasmine-sinon.html
Upvotes: 2
Reputation: 1006
As mentioned in the comments, I found out that, this is due to the "new" in the model definition.
So, after changing,
var Photo = new Backbone.Model.extend({
to
var Photo = Backbone.Model.extend({
The error disappeared.
Upvotes: 7
Reputation: 18597
The code snippet below is probably the culprit.
this.bind("change:title", function(){
var title = this.get("title");
console.log("My title has been changed to.." + title);
});
In Javascript, the scope context of the this keyword is based upon the function it is in. Since this is inside an anonymous function (this.bind("change:title", function()), then this has changed its scope.
The easy solution is to use a closure to set this to another variable outside the anonymous function, and then you can use the variable inside the anonymous function.
Showing a code example will probably better explain it. Update your initialize method to the following.
initialize: function(){
console.log('this model has been initialized');
var self = this;
this.bind("change:title", function(){
var title = self.get("title");
console.log("My title has been changed to.." + title);
});
},
You will also have the same problem in the setTitle() method. You will need to add this line of code in the initialize() method to correctly set the context of this.
_.bindAll(this, "setTitle");
Upvotes: 1