10

TLDR; what's the proper way to mock a React component imported from a third-party library?

I'm testing a component called <App/>. It consumes a 3rd part component called <Localize/> provided by a library called localize-toolkit.

I'm having some trouble mocking <Localize/> using Jest.

Here is how I've tried mocking it.

jest.mock('localize-toolkit', () => ({
  // Normally you pass in a key that represents the translated caption.
  // For the sake of testing, I just want to return the key.
  Localize: () => (key:string) => (<span>{key}</span>)
}));

And I've written a unit test for <App/> that looks like this.

it('Test', () => {
    const component = render(<App/>);
    expect(component).toMatchSnapshot();
  }
)

It will pass, however this is the warning message returned.

Functions are not valid as a React child. This may happen if you return a Component instead of <Component /> from render.

And when I look at the snapshot, I get a series of periods "..." where the localized caption should appear.

Am I not mocking the Localize component properly?

skyboyer
  • 22,209
  • 7
  • 57
  • 64
Cog
  • 1,545
  • 2
  • 15
  • 27

2 Answers2

14

Here's how I ended up doing it.

Note how the third-party component Localize needs to be returned as a function.

jest.mock('localize-toolkit', () => ({
  Localize: ({t}) => (<>{t}</>)
}));

and in case there are multiple components, and you only want to mock one of them, you can do this:

jest.mock("localize-toolkit", () => {
    const lib = jest.requireActual("localize-toolkit");

    return {
        ...lib,
        Localize: ({t}) => (<>{t}</>), 
    };
});
Cog
  • 1,545
  • 2
  • 15
  • 27
2

We can mock the 3rd party library for example in my case i need to mock react-lazyload

Component.tsx

import LazyLoad from 'react-lazyload';

render() {
  <LazyLoad><img/></LazyLoad>
}

In jest.config.js

module.exports = {
  moduleNameMapper: {
   'react-lazyload': '/jest/__mocks__/react-lazyload.js',
  }
}

In jest/mocks/react-lazyload.js

import * as React from 'react';

jest.genMockFromModule('react-lazyload');

const LazyLoad = ({children}) => <>{children}</>;

module.exports = { default: LazyLoad };
smsivaprakaash
  • 1,564
  • 15
  • 11