6

Looking for some recommendations on how to mock the .cancel method in a debounce from lodash.

I have a function that is calling debounce and then later utilizing the returned debounce value to call debouncedThing.cancel().

I am able to mock debounce just fine in my tests except for when my function is called .cancel().

At the top of my unit tests I am currently doing:

jest.mock('lodash/debounce', () => fn => fn));

The above mock has worked fine except for in the place where I am calling debouncedThing.cancel(). In those test, I get an error that debouncedThing.cancel() is not a function.

Psuedo code of where I am using debounce looks like this:

const debouncedThing = debounce(
  (myFunc, data) => myFunc(data),
  DEBOUNCE_DELAY_TIME,
);

const otherFunc = () => {
 /* omitted */
 debouncedThing.cancel();
}
skyboyer
  • 22,209
  • 7
  • 57
  • 64
Steph M
  • 2,152
  • 1
  • 12
  • 11

1 Answers1

6

You just need to add the cancel function to fn:

jest.mock('lodash/debounce', () => fn => {
  fn.cancel = jest.fn();
  return fn;
});

Example of it in use:

const debounce = require('lodash/debounce');

test('debouncedThing', () => {
  const thing = jest.fn();
  const debouncedThing = debounce(thing, 1000);

  debouncedThing('an arg');
  expect(thing).toHaveBeenCalledWith('an arg');  // Success!

  debouncedThing.cancel();  // no error
  expect(debouncedThing.cancel).toHaveBeenCalled();  // Success!
});
Brian Adams
  • 43,011
  • 9
  • 113
  • 111
  • 1
    ...also, depending on your code and what you are trying to test you might be able to avoid needing to mock `debounce` by using [Timer Mocks](https://jestjs.io/docs/en/timer-mocks.html) instead. – Brian Adams Mar 26 '19 at 00:50