Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jest/enzyme mock function in functional component

I have a functional component and I wanted to test it with mock function (simplified demonstration)

const remove = () => {
  ... do something
}

const removeButton = (props) => (
  <Button onClick={() => remove()}>
    Remove
  </Button>
);

I tried with this test case

it('test remove button', () => {
  const test = shallow(<removeButton/>)
  const mockFunction = jest.fn()
  test.instance().remove = mockFunction
  test.find('Button').simulate('click')
  expect(mockFunction).toHaveBeenCalled()
})

.instance().remove could not mock the function because it is out of scope. How would I mock the function remove ?

like image 623
user10200079 Avatar asked Aug 08 '18 22:08

user10200079


People also ask

How do you mock a function in a React functional component?

To mock a React component, the most straightforward approach is to use the jest. mock function. You mock the file that exports the component and replace it with a custom implementation. Since a component is basically a function, the mock should also return a function.

How do you mock a function in Jest for a test?

There are two ways to mock functions: Either by creating a mock function to use in test code, or writing a manual mock to override a module dependency.

Can we use Render () inside functional component?

There is no render method used in functional components. With functional components there are fewer lines of code another positive to this is that the fewer lines of code a developer has to read and write, the faster and easier their code is to comprehend.


1 Answers

Here is a working example:

// ---- comp.js ----
import * as React from 'react';
import * as comp from './comp';

export const remove = () => {
  // ...do something
}

export const RemoveButton = (props) => (
  <div onClick={() => comp.remove()}>
    Remove
  </div>
);


// ---- comp.test.js ----
import * as React from 'react';
import { shallow } from 'enzyme';

import * as comp from './comp';

describe('removeButton', () => {
  it('should call remove on click', () => {
    const mock = jest.spyOn(comp, 'remove');
    mock.mockImplementation(() => {});
    const component = shallow(<comp.RemoveButton />);
    component.find('div').simulate('click');
    expect(mock).toHaveBeenCalled();
    mock.mockRestore();
  });
});

Note that to mock remove you need to export it and you need to import the module back into itself and use the import within your component.

Having said that, I agree that passing remove in as a prop is a better approach. It is much easier to test and makes your components more reusable.

like image 120
Brian Adams Avatar answered Sep 21 '22 14:09

Brian Adams