Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

useEffect hook not being mocked by jest.spyOn

I'm new to React Hooks and what I'm trying to achieve is to test a React component (called CardFooter) that contains a call to useEffect hook that gets triggered a global context variable is modified.

CardFooter.js:

const CardFooter = props => {
  const [localState, setLocalState] = useState({
    attachmentError: false
  });
  const globalContext = useContext(GlobalContext);
  React.useEffect(()=> {
    setLocalState({
    ...localState,
    attachmentError: globalContext.data.attachmentError
  });
 },[globalContext.data.attachmentError]);
}

CardFooter.test.js:

import Enzyme, { shallow } from 'enzyme';    
Enzyme.configure({ adapter: new Adapter() });
describe('<CardFooter  />', () => {
  let useEffect;
  const mockUseEffect = () => {
    useEffect.mockImplementation(f => f());
  };

  useEffect = jest.spyOn(React, "useEffect");
  mockUseEffect(); //

  it('should render correctly with no props.', () => {
  }

  const mockUseEffect = () => {
    useEffect.mockImplementation(f => f());
  };

  useEffect = jest.spyOn(React, "useEffect");
  mockUseEffect();

  const wrapper = shallow(<CardFooter />);
  expect(toJson(wrapper)).toMatchSnapshot();

});

the error that I'm getting when running the test is:

TypeError: Cannot read property 'attachmentError' of undefined

I tried the approach presented here: https://medium.com/@pylnata/testing-react-functional-component-using-hooks-useeffect-usedispatch-and-useselector-in-shallow-9cfbc74f62fb . However it seems that shallow does not pick the mocked useEffect implementation. I also tried mocking the useContext and the globalContext.data.attachmentError. Nothing seems to work.

like image 481
otto Avatar asked Jan 05 '20 16:01

otto


People also ask

What is the use of Jest spyOn?

The spyOn function is one of the most powerful utility functions in Jest. It allows you to spy on a function, observe interactions, and mock them accordingly.

How do you mock react State in Jest?

To enable us to mock useState, we use React. useState (line #5) instead of using the usual named import (i.e. import { useState } from 'react'). Below is our Jest unit test for the component. Before rendering the component for testing, we create a constant 'setStateMock' and mock it with a jest function jest.

How does useEffect () hook gets executed?

To trigger the useEffect hook before unmounting the component from the screen, we can return a function from the callback function. The function returned by the callback will be executed before that component is unmounted.

How do you test for useEffect hooks?

To test the component update useEffect hook you'd simply trigger state updates and check for effects in rendered elements. Redux hooks can be tested by mocking them and their implementation.


1 Answers

Try this. Notice the "jest.spyOn" is placed inside "beforeEach"

  beforeEach(() => {
    jest.spyOn(React, "useEffect").mockImplementationOnce(cb => cb()());
    
     // .... other things ....
  }
like image 57
xeiton Avatar answered Sep 18 '22 18:09

xeiton