Unexpected Jest Errors when Mocking Uppy

614 views Asked by At

I'm attempting to mock the Uppy class from the uppy package in a Jest unit test following guidance from this previously answered question. My failing code is below:

import Uppy from '@uppy/core';

describe('MyComponent', () => {
  it('renders', () => {
    jest.mock('@uppy/core', () => {
      return {
        Uppy: jest.fn().mockImplementation(() => {
          return {};
        }),
      };
    });
    
    new Uppy();
    expect(Uppy).toHaveBeenCalledTimes(1);
  });
});

The test fails with the following error message:

Matcher error: received value must be a mock or spy function

Received has type:  function
Received has value: [Function Uppy]

It appears that the default export from @uppy/core is the Uppy class, so my expectation is that the provided code would mock the class' constructor, however this doesn't seem to be the case.

Package versions:

  • Uppy: 2.1.2
  • Jest: 27.4.7
1

There are 1 answers

0
Andrei Gătej On

I think the problem is that you're using jest.mock() at the wrong time. In other words, I think it's too late to call jest.mock() inside a test case because the package has already been imported by that time.

I'm not sure what the canonical way of doing this is, but here is how React does it:

  • it has a separate file were jest.mock() is called
  • that file's path from above is the value of Jest's globalSetup option; as you can see, this option is the in the config.base.js file:
module.exports = {
  globalSetup: require.resolve('./setupGlobal.js'),
}
  • when the test script is run, it will choose the config based on the provided argument(s)

  • an example of such config would be this file which, as you can see, extends config.base, which is where the globalSetup option has been set

/* ... */
const baseConfig = require('./config.base');

module.exports = Object.assign({}, baseConfig, { /* ... */ });
/* ... */

So, I'd say that making use of that globalSetup option should solve the problem.