Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SpyOn a mocked jest module not spying properly

I have simple service that I need unit tested using jest:

the crux of the code is this:

 domtoimage.toBlob(node, {filter: filter})
    .then(function (blob) {
      FileSaver.saveAs(blob, fileName);
 });

I have wrote my unit test module as such:

import FileSaver from "file-saver";
import domtoimage from "dom-to-image";


jest.mock('dom-to-image', () => {
  return {
    toBlob: (arg)=>{
      let promise = new Promise((resolve, reject) => {
        resolve('myblob')
      });
      return promise;
    }
  }
});
jest.mock('file-saver', ()=>{
  return {
    saveAs: (blob, filename) =>{
      return filename;
    }
  }
});

And in my test, I have the following spy set up

const spy = jest.spyOn(FileSaver, 'saveAs');

and calling my in-test function.

however, the expect statement: expect(spy).toBeCalled() returns false:

expect(jest.fn()).toBeCalled()

However, in webstorm, when I debug the unit test, I can clearly see that my mocked function is being called (the breakpoint is reached inside function).

What am i missing?

like image 714
nate Avatar asked Jun 12 '18 05:06

nate


People also ask

How do you spyOn a module in Jest?

To spy on an exported function in jest, you need to import all named exports and provide that object to the jest. spyOn function. That would look like this: import * as moduleApi from '@module/api'; // Somewhere in your test case or test suite jest.

Does Jest spyOn mock?

Before every function is run in the file, jest will mock , and after every , jest will restore the function to its original implementation. Using the hooks for setup ensures that every test is fresh and independent of each other.

What is the use of spyOn in Jest?

Jest has a spyOn function, which can resolve the problem and make the test much better. jest. spyOn allows a method in an object to be mocked.

What is the difference between spyOn and mock in Jest?

jest. mock does this automatically for all functions in a module. jest. spyOn does the same thing but allows restoring the original function.


1 Answers

Suggestion 1

Maybe spyOn and module mocks don't play well together. You could try using a jest.fn() directly inside the module mock like so

jest.mock('file-saver', ()=>{
  return {
    saveAs: jest.fn((blob, filename) => {
      return filename;
    })
  }
});

and then

expect(FileSaver.saveAs).toBeCalled()

Remember to call jest.clearAllMocks() or similar between tests.

Suggestion 2 I've had issues with jest.mock working in unexpected ways with the jest module cache, especially when working with singleton imports. Maybe you have this issue. if file-saver and dom-to-image don't have any state initialized or side-effects on import time you should be able to swap jest.mock out for overrides of the functions you need to mock.

beforeEach(() => {
  FileSaver.saveAs = jest.fn(...);
  domtoimage.toBlob = jest.fn(...);
})
like image 92
Red Mercury Avatar answered Sep 17 '22 12:09

Red Mercury