Search code examples
javascriptunit-testingjestjsdebouncing

Jest unit test for a debounce function


I am trying to write a unit test for a debounce function. I'm having a hard time thinking about it.

This is the code:

function debouncer(func, wait, immediate) {
  let timeout;

  return (...args) => {
    clearTimeout(timeout);

    timeout = setTimeout(() => {
      timeout = null;
      if (!immediate) 
        func.apply(this, args);
    }, wait);

    if (immediate && !timeout) 
      func.apply(this, args);
  };
}

How should I start?


Solution

  • You will probably want to check the logic in your debouncer function:

    Having said that, it sounds like your real question is about testing debounced functions.

    Testing debounced functions

    You can test that a function is debounced by using a mock to track function calls and fake timers to simulate the passage of time.

    Here is a simple example using a Jest Mock Function and Sinon fake timers of a function debounced using debounce() from Lodash:

    const _ = require('lodash');
    import * as sinon from 'sinon';
    
    let clock;
    
    beforeEach(() => {
      clock = sinon.useFakeTimers();
    });
    
    afterEach(() => {
      clock.restore();
    });
    
    test('debounce', () => {
      const func = jest.fn();
      const debouncedFunc = _.debounce(func, 1000);
    
      // Call it immediately
      debouncedFunc();
      expect(func).toHaveBeenCalledTimes(0); // func not called
    
      // Call it several times with 500ms between each call
      for(let i = 0; i < 10; i++) {
        clock.tick(500);
        debouncedFunc();
      }
      expect(func).toHaveBeenCalledTimes(0); // func not called
    
      // wait 1000ms
      clock.tick(1000);
      expect(func).toHaveBeenCalledTimes(1);  // func called
    });