无法测试防抖的Backbone视图事件

4
当我不对该函数进行节流/去抖动时,测试通过。
然而,当我对事件进行去抖动以防止服务器被淹没时,测试不再通过。Mocha输出了AssertionError: 预期execute至少被调用一次,但它从未被调用 应该注意的是,去抖动调用在实际代码中没有错误。这就是为什么我非常困惑为什么测试失败的原因。 测试:
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()
    });
});

Un-throttled: 没有限速
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个回答

8

使用UnderscoreJSSinonJS时存在问题。

  • UnderscoreJS中的debounce函数使用了_.now
  • SinonJS覆盖了Date对象,但没有覆盖_.now

为了测试目的,在测试的启动文件中我替换了_.now

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

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

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接