I am using Jasmine to test a Backbone.js view within a Require.js module.
Why does my test fail if I don't wrap the callback in an anonymous function?
Here's the test:
describe("view extension", function () {
// extendedView is an instance of ExtendedView()
spyOn(extendedView, 'onOpen');
// open the element, which should trigger an event
extendedView.open();
expect(extendedView.onOpen).toBeDefined();
expect(extendedView.onOpen).toHaveBeenCalled();
});
Failing:
var BaseView = Backbone.View.extend({
open: function () {
this.trigger('open');
}
});
var ExtendedView = BaseView.extend({
initialize: function () {
var self = this;
self.on('open', self.onOpen);
},
onOpen: function() {
console.log('I heard myself open');
}
});
Passing with the following revision in .initialize()
:
self.on('open', function () { self.onOpen() });
The reason it is not working is that you are installing the spy on an instance and doing this after the event handler is bound. The sequence of event is roughly like this:
The instance that is going to be assigned to extendedView
is created so ExtendedView
's initialize
method executes self.on('open', self.onOpen);
. At that time self.onOpen
evaluates to the original function defined by the ExtendedView
class.
Then you set a spy on extendedView.onOpen
. This changes the value of onOpen
for extendedView
(and only for extendedView
) to that of a new spy.
extendedView.open()
is called. Because self.on
was called originally with the value of self.onOpen
set for the ExtendedView
class, it is this original function which is called , not the spy that now resides in extendedView.onOpen
.
The reason it work when you use the anonymous function is that the anonymous function gets the value of self.onOpen
whenever an open
event happens, which in your test means this value is obtained after you've set the spy.
You'd have to spy on the class methods rather than on the instance. Something like:
spyOn(ExtendedView.prototype, 'onOpen');
[...]
expect(ExtendedView.prototype.onOpen).toBeDefined();
expect(ExtendedView.prototype.onOpen).toHaveBeenCalled();
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.