Testing React components that fetches data using Hooks

mthmulders picture mthmulders · Mar 7, 2019 · Viewed 21k times · Source

My React-application has a component that fetches data to display from a remote server. In the pre-hooks era, componentDidMount() was the place to go. But now I wanted to use hooks for this.

const App = () => {
  const [ state, setState ] = useState(0);
  useEffect(() => {
    fetchData().then(setState);
  });
  return (
    <div>... data display ...</div>
  );
};

And my test using Jest and Enzyme looks like this:

import React from 'react';
import { mount } from 'enzyme';
import App from './App';
import { act } from 'react-test-renderer';

jest.mock('./api');

import { fetchData } from './api';

describe('<App />', () => {
  it('renders without crashing', (done) => {
    fetchData.mockImplementation(() => {
      return Promise.resolve(42);
    });
    act(() => mount(<App />));
    setTimeout(() => {
      // expectations here
      done();
    }, 500);
  });  
});

The test succeeds, but it logs a few warnings:

console.error node_modules/react-dom/cjs/react-dom.development.js:506
    Warning: An update to App inside a test was not wrapped in act(...).

    When testing, code that causes React state updates should be wrapped into act(...):

    act(() => {
    /* fire events that update state */
    });
    /* assert on the output */

    This ensures that you're testing the behavior the user would see in the browser. Learn more at (redacted)
        in App (created by WrapperComponent)
        in WrapperComponent

The only update to the App component happens from the Promise callback. How can I ensure this happens within the act block? The docs clearly suggest to have assertions happen outside the act block. Besides, putting them inside doesn't change the warning.

Answer

Shaphan picture Shaphan · Jan 21, 2020

That issue is caused by many updates inside Component.

I got the same issue, this would solve the issue.

await act( async () => mount(<App />));