Javascript 用Jasmine监视事件回调

Javascript 用Jasmine监视事件回调,javascript,backbone.js,requirejs,closures,jasmine,Javascript,Backbone.js,Requirejs,Closures,Jasmine,我正在使用Jasmine测试Require.js模块中的Backbone.js视图 如果我没有将回调封装在匿名函数中,为什么测试会失败 以下是测试: describe("view extension", function () { // extendedView is an instance of ExtendedView() spyOn(extendedView, 'onOpen'); // open the element, which should trigger

我正在使用Jasmine测试Require.js模块中的Backbone.js视图

如果我没有将回调封装在匿名函数中,为什么测试会失败

以下是测试:

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();
});
失败:

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');
    }
});
.initialize()
中传递以下版本:


它不起作用的原因是您正在实例上安装spy,并在绑定事件处理程序后执行此操作。事件的顺序大致如下:

  • 创建要分配给
    extendedView
    的实例,以便
    extendedView
    initialize
    方法执行
    self.on('open',self.onOpen')当时
    self.onOpen
    计算为
    扩展视图
    类定义的原始函数

  • 然后在
    extendedView.onOpen
    上设置一个间谍。这将
    extendedView
    onOpen
    值(以及
    extendedView
    值)更改为新spy的值

  • 调用了extendedView.open()。因为最初调用
    self.on
    时,为
    ExtendedView
    类设置了
    self.onOpen
    值,所以调用的是这个original函数,而不是现在驻留在
    ExtendedView.onOpen
    中的间谍

  • 当您使用匿名函数时,它工作的原因是每当发生
    打开
    事件时,匿名函数都会获取
    self.onOpen
    的值,这在您的测试中意味着该值是在设置间谍后获得的

    您必须监视类方法,而不是实例。比如:

        spyOn(ExtendedView.prototype, 'onOpen');
    
        [...]    
    
        expect(ExtendedView.prototype.onOpen).toBeDefined();
        expect(ExtendedView.prototype.onOpen).toHaveBeenCalled();
    

    试图使用
    .prototype
    访问类时,测试中会出现错误:
    spyOn无法为onOpen()找到要监视的对象。
    。这可能是因为模块是通过
    require
    拉入测试的。
        spyOn(ExtendedView.prototype, 'onOpen');
    
        [...]    
    
        expect(ExtendedView.prototype.onOpen).toBeDefined();
        expect(ExtendedView.prototype.onOpen).toHaveBeenCalled();