admin管理员组

文章数量:1287632

When I am not throttling/debouncing the function the test passes.

However when I debounce the event to prevent flooding the server the test no longer passes. Mocha outputs AssertionError: expected execute to have been called at least once, but it was never called

It should be noted that the debounced call works without errors in the live code. Which is why I'm thoroughly confused why the test fails.

The Test:

describe('When information is entered into the search fields', function () {
    it('vents up the search:for:churches mand', 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);
    }

});

Throttled:

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)

});

Edit: I have also posted a related follow-up question:

When I am not throttling/debouncing the function the test passes.

However when I debounce the event to prevent flooding the server the test no longer passes. Mocha outputs AssertionError: expected execute to have been called at least once, but it was never called

It should be noted that the debounced call works without errors in the live code. Which is why I'm thoroughly confused why the test fails.

The Test:

describe('When information is entered into the search fields', function () {
    it('vents up the search:for:churches mand', 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);
    }

});

Throttled:

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)

});

Edit: I have also posted a related follow-up question: https://stackoverflow./questions/21167488/how-to-test-a-debounced-throttled-backbone-view-event-with-mocha-to-ensure-its-a

Share Improve this question edited May 23, 2017 at 12:06 CommunityBot 11 silver badge asked Jan 15, 2014 at 22:17 JonathanWJonathanW 4243 silver badges17 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 8

There is a problem, when using UnderscoreJS with SinonJS.

  • The debounce function in UnderscoreJS uses _.now.
  • SinonJS covers the Date object, but doesn't cover _.now.

For testing purposes, i replace _.now in the test's bootstrap file:

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

Simon's approach worked great for most cases but I kept bumping into different situations that were causing more errors. After spending more time with it and looking at sinon's documentation I think I have a better approach.

Sinon's Fake Timers to the rescue.

describe('When information is entered into the search fields', function () {
    it('vents up the search:for:churches mand', 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()    
    });
});

Throttling anything means the execution will be asynchronous. This is why it fails in your tests, because the App.execute method is not call right away, so when you assert it have been called, it haven't yet.

In this case, don't use Sinon. Just manually stub your method:

describe('When information is entered into the search fields', function () {
    it('vents up the search:for:churches mand', 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();
    });
});

本文标签: javascriptUnable to test debounced Backbone view eventStack Overflow