Sinon似乎没有窥探事件处理程序回调 [英] Sinon does not seem to spy for an event handler callback

查看:163
本文介绍了Sinon似乎没有窥探事件处理程序回调的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Jasmin,Simon和jasmin-simon测试骨干视图。

I'm testing a backbone view with Jasmin, Simon and jasmin-simon.

以下是代码:

var MessageContainerView = Backbone.View.extend({
    id: 'messages',
    initialize: function() {
        this.collection.bind('add', this.addMessage, this);
    },
    render: function( event ) {
        this.collection.each(this.addMessage);
        return this;
    },
    addMessage: function( message ) {
        console.log('addMessage called', message);
        var view = new MessageView({model: message});
        $('#' + this.id).append(view.render().el);
    }
});

实际上,我的所有测试都只通过一次。我想检查每当我将项目添加到 this.collection 时,都会调用 addMessage

Actually, all my tests pass but one. I would like to check that addMessage is called whenever I add an item to this.collection.

describe('Message Container tests', function(){
    beforeEach(function(){
        this.messageView = new Backbone.View;
        this.messageViewStub = sinon.stub(window, 'MessageView').returns(this.messageView);

        this.message1 = new Backbone.Model({message: 'message1', type:'error'});
        this.message2 = new Backbone.Model({message: 'message2', type:'success'});
        this.messages = new Backbone.Collection([
            this.message1, this.message2            
        ]); 

        this.view = new MessageContainerView({ collection: this.messages });
        this.view.render();

        this.eventSpy = sinon.spy(this.view, 'addMessage');
        this.renderSpy = sinon.spy(this.messageView, 'render');
        setFixtures('<div id="messages"></div>');
    });
    afterEach(function(){
        this.messageViewStub.restore();
        this.eventSpy.restore();
    });

    it('check addMessage call', function(){
        var message = new Backbone.Model({message: 'newmessage', type:'success'});
        this.messages.add(message);

        // TODO: this fails not being called at all
        expect(this.view.addMessage).toHaveBeenCalledOnce();
        // TODO: this fails similarly
        expect(this.view.addMessage).toHaveBeenCalledWith(message, 'Expected to have been called with `message`');
        // these pass
        expect(this.messageView.render).toHaveBeenCalledOnce();
        expect($('#messages').children().length).toEqual(1);
    });
});

正如你所看到的那样,确实调用了addMessage 。 (它记录到控制台,并且它应该调用 this.messageView 。我在间谍中错过了什么 addMessage 电话?

As you can see addMessage is called indeed. (It logs to the console and it calls this.messageView as it should. What do I miss in spying for addMessage calls?

谢谢,Viktor

推荐答案

我不退出当然,据我所知,会发生以下情况:

I'm not quit sure but, as I understand it, the following happens:


  1. 您创建一个新视图,调用初始化函数并将 view.addMessage 绑定到您的集合。

  2. 执行此操作,Backbone获取功能并存储它在你的收藏的事件存储中。

  3. 然后你监视 view.addMessage 这意味着你用间谍功能覆盖它。这样做对收集事件存储中存储的函数没有影响。

  1. You create a new view which calls the initialize function and bind your view.addMessage to your collection.
  2. Doing this, Backbone take the function and store it in the event store of your collection.
  3. Then you spy on view.addMessage which means you overwrite it with a spy function. Doing this will have no effect on the function that is stored in the collection event store.

所以他们的测试存在一些问题。你认为有很多依赖,你没有嘲笑。你创建了一堆额外的Backbone模型和集合,这意味着你不只测试你的竞争w还有Backbones Collection和Model功能。

So their are some problems with your test. You view has a lot of dependencies that you not mock out. You create a bunch of additional Backbone Models and Collections, which means you not test only your view but also Backbones Collection and Model functionality.

您不应该测试 collection.bind 是否可行,但是你已经使用参数'add',this.addMessage,这个

You should not test that collection.bind will work, but that you have called bind on the collection with the parameters 'add', this.addMessage, this

initialize: function() {
    //you dont 
    this.collection.bind('add', this.addMessage, this);
},

因此,它很容易模拟集合:

So, its easy to mock the collection:

var messages = {bind:function(){}, each:function(){}}
spyOn(messages, 'bind');
spyOn(messages, 'each');
this.view = new MessageContainerView({ collection: messages });

expect(message.bind).toHaveBeenCalledWith('bind', this.view.addMessage, this.view);

this.view.render()

expect(message.each).toHaveBeenCalledWith(this.view.addMessage);

... and so on

这样做你只测试你的代码并没有依赖Backbone。

Doing it this way you test only your code and have not dependencies to Backbone.

这篇关于Sinon似乎没有窥探事件处理程序回调的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆