When I'm trying to test _.debounce function like in this qunit test using jasmine something strange happens.
Seems like it could be tested using jasmine.Clock.useMock()
...
But when I write:
it('_.debounce()', function () {
var spy = jasmine.createSpy('debounce'),
debouncedSpy = _.debounce(spy, 100);
jasmine.Clock.useMock();
// direct calls
debouncedSpy();
debouncedSpy();
debouncedSpy();
// timed out calls
setTimeout(debouncedSpy, 60);
setTimeout(debouncedSpy, 120);
setTimeout(debouncedSpy, 180);
setTimeout(debouncedSpy, 240);
setTimeout(debouncedSpy, 300);
jasmine.Clock.tick(300);
expect(spy).toHaveBeenCalled();
jasmine.Clock.tick(400);
expect(spy).toHaveBeenCalled();
jasmine.Clock.tick(1000);
expect(spy.callCount).toBe(1);
});
It doesn't work (call count is equal 3). But without direct calls (or when I'm using setTimeout(..., 0)
) everything works fine. What I'm doing wrong?
Also I've try to do it through runs
and waits
, and it works. But why it doesn't work in previous example?
it('should be called once', function () {
var spy = jasmine.createSpy('debounce'),
debouncedSpy = _.debounce(spy, 100);
runs(function () {
debouncedSpy();
debouncedSpy();
debouncedSpy();
expect(spy).not.toHaveBeenCalled();
setTimeout(debouncedSpy, 60);
setTimeout(debouncedSpy, 120);
setTimeout(debouncedSpy, 180);
setTimeout(debouncedSpy, 240);
setTimeout(debouncedSpy, 300);
});
waits(800);
runs(function () {
expect(spy.callCount).toBe(1);
});
});
The jasmine mock clock only changes the behavior of
setTimeout
and it's ilk, it currently doesn't mock outDate
see https://github.com/pivotal/jasmine/issues/361 and https://github.com/pivotal/jasmine/pull/455. Usingruns
andwaitsFor
(or in jasmine 2.0done
callbacks), actually lets the time pass so the browser actually changes theDate
value so the date math that happens insidedebounce
adds up.Until https://github.com/pivotal/jasmine/issues/361 and https://github.com/pivotal/jasmine/pull/455. are released, you add this to your tests to have Jasmine skip the debounce delay.