Я наконец нашел решение для багги таймеров Sinon, поскольку они внутренне перекрывают объект Date
, setTimeout()
, setInterval()
и т. Д.
Вопрос в том, если мыготовы изменить наш код, чтобы встряхнуть тест или еще хуже интегрировать условия тестирования в наш код.
Решение состоит в том, чтобы запустить таймер с ... временем!
/*** file 'g3.debounceTest.js' ***/
describe('g3.debounce', function() {
it('should not run debounced function with: 1 call at elapsed < delay & fireLast: true', function() {
var clock = sinon.useFakeTimers();
// sinon remedy avoids buggy behavior
clock.tick(1000);
//console.log(Date.now());
var delay = 100;
var spy = sinon.spy();
var targetFn = function(){console.log('eventually debounced was called!'); spy()};
var delayedFn = g3.debounce(targetFn, {delay: delay, fireFirst: false, fireLast: true});
// for lodash:
//var delayedFn = _.debounce(targetFn, delay, {leading: false, trailing: true});
delayedFn();
clock.tick(delay - 1);
//console.log(Date.now());
clock.restore();
sinon.assert.notCalled(spy);
});
it('should run debounced function once with: 1 call at elapsed < delay & fireFirst: true', function() {
var clock = sinon.useFakeTimers();
// sinon remedy avoids buggy behavior
clock.tick(1000);
//console.log(Date.now());
var delay = 100;
var spy = sinon.spy();
var targetFn = function(){console.log('eventually debounced was called!'); spy()};
var delayedFn = g3.debounce(targetFn, {delay: delay, fireFirst: true, fireLast: false});
// for lodash:
//var delayedFn = _.debounce(targetFn, delay, {leading: true, trailing: false});
delayedFn();
clock.tick(delay - 1);
//console.log(Date.now());
clock.restore();
sinon.assert.calledOnce(spy);
});
it('should run debounced function once with: 3 calls at elapsed < delay & fireFirst: true', function() {
var clock = sinon.useFakeTimers();
// sinon remedy avoids buggy behavior
clock.tick(1000);
//console.log(Date.now());
var delay = 100;
var spy = sinon.spy();
var targetFn = function(){console.log('eventually debounced was called!'); spy()};
var delayedFn = g3.debounce(targetFn, {delay: delay, fireFirst: true, fireLast: false});
// for lodash:
//var delayedFn = _.debounce(targetFn, delay, {leading: true, trailing: false});
/* 1 */delayedFn();
/* after 99ms */
clock.tick(delay - 1);
//console.log(Date.now());
/* 2 */delayedFn();
/* after 99ms */
clock.tick(delay - 1);
//console.log(Date.now());
/* 3 */delayedFn();
clock.restore();
sinon.assert.calledOnce(spy);
});
it('should run debounced function once with: 3 calls at elapsed < delay & fireLast: true', function() {
var clock = sinon.useFakeTimers();
// sinon remedy avoids buggy behavior
clock.tick(1000);
//console.log(Date.now());
var delay = 100;
var spy = sinon.spy();
var targetFn = function(){console.log('eventually debounced was called!'); spy()};
var delayedFn = g3.debounce(targetFn, {delay: delay, fireFirst: false, fireLast: true});
// for lodash:
//var delayedFn = _.debounce(targetFn, delay, {leading: true, trailing: false});
/* 1 */delayedFn();
/* after 99ms */
clock.tick(delay - 1);
//console.log(Date.now());
/* 2 */delayedFn();
/* after 99ms */
clock.tick(delay - 1);
//console.log(Date.now());
/* 3 */delayedFn();
/* after 100ms */
clock.tick(delay);
clock.restore();
sinon.assert.calledOnce(spy);
});
});
/***end file 'g3.debounceTest.js' ***/
Я также ввел spy()
внутрь обратного вызова, поскольку хотел посмотреть, что происходит с этим обратным вызовом, и неожиданно заметил, что обратный вызов запускается после того, как мы вызываем clock.restore();
, но sinon
не имеет способа проверить это и остается полностьюне зная, что происходит после clock.restore();
.
Вот почему я заставил написать clock.tick(delay);
в последнем случае, чтобы позволить sinon
«увидеть», что происходит последний вызов.
И наконец, если у вас будет больше идей для тестирования такого асинхронного кода, я бы с удовольствием их увидел.