React (v16.14.0) Testing w/ Enzyme/Jest: Component state rendering data on fetch that is inside a useEffect

41 Views Asked by At

I am having issue with testing a component that makes a fetch call inside a useEffect. What's happening is that, state is being updated but the component is not rendering the data from the fetch call that was set via the useEffect. It works fine the application is running, just not in the context of testing. Example below.

Functional Component

export const MyComponent: FunctionComponent = () => {

    const [data, setData] = useState([]); // <-- assume this is a list/array of numbers 1-20

    useEffect(() => {
       fetchData().then((response) => {
           setData(response)
       });
    }, []);

    return (
      <div id="the-data-list">
          { data?.length > 0 && data?.map((d) => (<span id=`the-data-${d}`>{ d }</span>)) }
      </div>
    );
}

Test Suite

describe('My Component Test Suite', () => {
    
    component = mount(<MyComponent />);

    it('should render the data', () => {
       const theData = component.find("#the-data-1").first();

       console.log(theData); <-- data is not rendered
    });

})

Odd thing is, putting a console.log right under where data is defined I can see that on the first render it's an empty []. On second render it has the data, but the data isn't rendered in the view. Any help or advice would be most appreciated.

Enzyme versions:

  • enzyme: 3.11.0
  • enzyme-adapter-react-16: 1.15.6
1

There are 1 best solutions below

0
Joseph Freeman On

So it turns out one of the reason why this didn't work for me is that the test data I was using was incorrect. It was an object instead of an array of object smh. I also added the usage of async and await. Below is the re-work of the example unit test suite.

describe('My Component Test Suite', () => {
    
    beforeAll(async () => {
        await act(async () => {
            component = mount(<MyComponent />);
        });
    });
    
    it('should render the data', async () => {
       const theData = component.find("#the-data-1").first();

       console.log(theData.debug()); <-- html is now rendered!!
    });
})