Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mock a non-default function using Jest and React

In a test file I need to render a component while mocking out some of its sub components. The file structure would look loosely something like this.

File 1

import {A, B} from 'a-module';

export function MyComponent() {
    return (
        <div>
            <A /> // I need to mock
            <B /> // these components out
        </div>
    );
}

File 2

import {MyComponent} from 'File 1';

/*
 * In this file I would like to render MyComponent but
 * have components A and B be replaced by mocks
 */

I have tried doing jest.mock('a-module', () => 'Blah'); but this is not successfully mocking the components. This works however when using default imports in File 1.

Any help in mocking out components A and B when rendering MyComponent in file 2 would be most appreciated!

like image 860
Jordan Epstein Avatar asked Dec 03 '18 22:12

Jordan Epstein


3 Answers

You can mock non defaults like this:

jest.mock('a-module', () => ({
  __esModule: true,
  default: () => 'Blah',
  A: () => 'Blah',
  B: () => 'Blah'
}));

https://remarkablemark.org/blog/2018/06/28/jest-mock-default-named-export/

or use __mocks__

as an alternative you could create a file under __mocks__ folder next to the original module with the same name as the module:

a_module_folder > 
    a-module.js
    __mocks__ >
        a-module.js

and that mock should just export the mocked versions:

export const A = () => 'Blah';
export const B = () => 'Blah';

and then just mock like this:

jest.mock('a-module');

for node_modules just put __mocks__folder on the same level as node_modules

https://jestjs.io/docs/en/manual-mocks

like image 173
Tiago Coelho Avatar answered Nov 17 '22 07:11

Tiago Coelho


Testing React components is mostly done with Enzyme, if you are trying to do it only with Jest you have probably picked the wrong tool. I can only guess why you need to mock a component, but most surely you will be able to achieve it with Enzyme.

There is Enzyme shallow rendering which is specifically created for testing React. Jest itself is not capable of rendering components. The definition as per Airbnb docs is:

Shallow rendering is useful to constrain yourself to testing a component as a unit, and to ensure that your tests aren't indirectly asserting on behaviour of child components.

Simply said it is going to render the tested component 1 level deep e.g.

// File2.js

import { MyComponent } from 'File1';
import { shallow } from 'enzyme';

describe('MyComponent', () => {
  it('should render shallowly my component', () => {
    const wrapper = shallow(<MyComponent />);
    console.log(wrapper.debug()); 
    // output:
    //   <div>
    //     <A />
    //     <B />
    //   </div>
    // Note: even if component <A /> is consisting of some markup, 
    // it won't be rendered 
  });
});

Essentially you don't need to mock any of its dependent components, these are already mocked with enzyme shallow()

What you can do instead is test when you pass certain props to <MyComponent />, dependent components <A /> and <B /> are receiving expected props.

const wrapper = shallow(<MyComponent foo={1} bar={2} />);
expect(wrapper.find('A').props().foo).toEqual(1);
expect(wrapper.find('B').props().bar).toEqual(2);
like image 33
Stefan J Avatar answered Nov 17 '22 08:11

Stefan J


If you have a react component which is not default export which is actually a good practice (since default exports should be avoided):

export function MyComponentX() {
    return (
        <div>...</div>
    );
}

You can mock it in jest easily:

jest.mock('path/to/MyComponentX', () => ({
  MyComponentX: () => <>MOCK_MY_COMPONENT_X</>,
}));
like image 30
CommonSenseCode Avatar answered Nov 17 '22 09:11

CommonSenseCode