'How to mock a 3rd party module that is just a function ('js-file-download')

I'm trying to write a test around download functionality in a React component that uses 'js-file-download'. I have been able to mock it a couple ways in my test:

import fileDownload from 'js-file-download'

jest.mock('js-file-download', () => jest.fn(console.trace))
// or
jest.mock('js-file-download', () => {
  return {
    __esModule: true,
    default: jest.fn(console.trace)
  }
})

both seem to work in that it prints a trace that looks correct. However:

expect(fileDownload).toHaveBeenCalled()

fails:

Expected number of calls: >= 1
Received number of calls:    0

Anyone know why it appears to call the mock, but doesn't register that it was called? Is there another way to tackle this? Thanks in advance!



Solution 1:[1]

This is what worked for me to fix ReferenceError: Cannot access 'mockFileDownload' before initialization

const mockFileDownload = jest.fn();
jest.mock('js-file-download', () => ({
    __esModule: true,
    default: () => mockFileDownload()
}));

To get the assertion to work we have to use waitFor()

....
await waitFor(() => {
    expect(mockFileDownload).toHaveBeenCalledTimes(1);
});
...

Solution 2:[2]

I believe I had it mocked correctly all along. The real issue was the timing and whatever was preventing me using 'await waitFor' as that was the key.

import mockFileDownload from 'js-file-download'

jest.mock('js-file-download', () => ({
  __esModule: true,
  default: jest.fn()
}))

...

await waitFor(() => expect(mockFileDownload).toBeCalled())

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 John