5

Jasmin、Simon、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);
    }
});

実際、すべてのテストに合格しましたが、1 つだけです。addMessageにアイテムを追加するたびに が呼び出されることを確認したいと思います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ですか?

ありがとう、ヴィクトル

4

2 に答える 2

6

アンドレアスがポイント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.

質問に対する直接的な答えは、アンドレアスが提案したすべての素晴らしいリファクタリングを無視して、次のMessageContainerView.prototype.addMessageようにスパイすることです。

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            
        ]);
        // Here
        this.addMessageSpy = sinon.spy(MessageContainerView.prototype, 'addMessage');
        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();
        MessageContainerView.prototype.addMessage.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.addMessageSpy).toHaveBeenCalledOnce();
        // TODO: this fails similarly
        expect(this.addMessageSpy).toHaveBeenCalledWith(message, 'Expected to have been called with `message`');
        // these pass
        expect(this.messageView.render).toHaveBeenCalledOnce();
        expect($('#messages').children().length).toEqual(1);
    });
});

とにかく、アンドレアスの提案を実装することをお勧めします。:)

于 2013-10-30T16:32:47.847 に答える