无法测试去抖动的Backbone视图事件

时间:2014-01-15 22:17:14

标签: javascript backbone.js underscore.js mocha sinon

当我没有限制/去除测试通过的功能时。

然而,当我辩论该事件以防止服务器泛滥时,测试不再通过。 Mocha输出AssertionError: expected execute to have been called at least once, but it was never called

应该注意的是,去抖动的呼叫在实时代码中没有错误地工作。这就是为什么我彻底搞砸为什么测试失败的原因。

测试:

describe('When information is entered into the search fields', function () {
    it('vents up the search:for:churches command', function () {
        var executeStub = sinon.stub(App, 'execute');

        view = new SearchForm()
        view.render();

        view.$el.find('input[name=church_name]').val('baptist')
        view.$el.find('input[name=zip]').val('61615')

        view.$el.find('input[name=zip]').trigger($.Event('keypress'))

        expect(executeStub).to.have.been.called

        view.close();
        PEP.execute.restore()
    });
});

无节流:

var SearchForm = Backbone.Marionette.ItemView.extend({

    template: 'search_form',
    events: {
        'keypress [data-search-field]' : 'searchForChurches'
    },

    searchForChurches: function() {
        console.log('not debounced')
        var searchData = Backbone.Syphon.serialize(this);
        App.execute("search:for:churches", searchData);
    }

});

经过调节

var SearchForm = Backbone.Marionette.ItemView.extend({

    template: 'search_form',
    events: {
        'keypress [data-search-field]' : 'searchForChurches'
    },

    searchForChurches: _.debounce(function() {
        console.log('debounced')
        var searchData = Backbone.Syphon.serialize(this);
        App.execute("search:for:churches", searchData);
    }, 200)

});

修改 我还发布了一个相关的后续问题:https://stackoverflow.com/questions/21167488/how-to-test-a-debounced-throttled-backbone-view-event-with-mocha-to-ensure-its-a

3 个答案:

答案 0 :(得分:8)

UnderscoreJS SinonJS 一起使用时出现问题。

  • UnderscoreJS 中的 debounce 功能使用 _。现在
  • SinonJS 涵盖了 Date 对象,但未涵盖 _。现在

出于测试目的,我在测试的bootstrap文件中替换 _。now

_.now = function() {
  return new Date().getTime();
};

答案 1 :(得分:5)

Simon的方法在大多数情况下都很有效但我不断遇到导致更多错误的不同情况。在花了更多的时间和查看sinon的文档后,我想我有更好的方法。

Sinon的Fake Timers来救援。

describe('When information is entered into the search fields', function () {
    it('vents up the search:for:churches command', function () {
        var clock = sinon.useFakeTimers();
        var executeStub = sinon.stub(App, 'execute');

        view = new SearchForm()
        view.render();

        view.$el.find('input[name=church_name]').val('baptist')
        view.$el.find('input[name=zip]').val('61615')

        view.$el.find('input[name=zip]').trigger($.Event('keypress'))
        clock.tick(200)

        expect(executeStub).to.have.been.called

        view.close();
        PEP.execute.restore()
        clock.restore()    
    });
});

答案 2 :(得分:1)

限制任何东西意味着执行将是异步的。这就是为什么它在测试中失败的原因,因为App.execute方法没有立即调用,所以当你断言它已被调用时,它还没有。

在这种情况下,请勿使用Sinon。只需手动存根您的方法:

describe('When information is entered into the search fields', function () {
    it('vents up the search:for:churches command', function (done) {
        var originalMethod = App.prototype.execute;

        App.prototype.execute = function () {
            App.prototype.execute = originalMethod;
            done(); // calling done will pass the test, otherwise it'll fail with a timeout
        };

        view = new SearchForm()
        view.render();

        view.$el.find('input[name=church_name]').val('baptist')
        view.$el.find('input[name=zip]').val('61615')

        view.$el.find('input[name=zip]').trigger($.Event('keypress'))

        view.close();
    });
});