2

I am trying to test a react functional component using hooks. The useEffect hook makes a call to a third part API which then calls setState on return.

I have the test working but keep getting a warning that an update to the component was not wrapped in act.

The problem I have is that the expectation is inside a moxios.wait promise and therefore I cannot wrap that in an act function and then assert on the result of that.

The test passes but I know not wrapping code that updates state in an act function could lead to false positives or uncovered bugs. I'm just wondering how I should be testing this.

I've tried using the new async await act function in the react 16.9.0 alpha release as well as numerous suggestions I've found in many github issues like jest setTimers and none seem to solve the issue.

The component

 const Benefits = props => {
  const [benefits, setBenefits] = useState([])
  const [editing, setEditing] = useState(false)
  const [editingBenefit, setEditingBenefit] = useState({id: null, name: '', category: ''})

  useEffect(() => {
    axios.get('#someurl')
      .then(response => {
        setBenefits(response.data)
    })
  }, [])
}

The test

describe('Benefits', () => {
  it('fetches the list of benefits from an api and populates the benefits table', (done) => {
    const { rerender } = render(<Benefits />)
    moxios.wait(() => {
      const request = moxios.requests.mostRecent()
      request.respondWith({
        status: 200,
        response: benefits
      }).then(() => {
        expect(document.querySelectorAll('tbody > tr').length).toBe(2)
        done()
      })
    })
  })
})

The test passes but I get the following warning

Warning: An update to Benefits 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.
    in Benefits (at benefits.spec.js:28)
Sam
  • 5,997
  • 5
  • 46
  • 66
  • https://stackoverflow.com/questions/56410688/how-to-test-useeffect-with-async-function-and-setstate-inside#comment99418488_56410688 – jonrsharpe Jun 05 '19 at 13:34
  • It's a known issue, see the question linked by @jonrsharpe. It's safe to ignore the warning for the time being – Gio Polvara Jun 05 '19 at 14:18
  • 1
    Thanks @Gpx. I thought the issue was supposed to be resolved by using the async act function but that still isn't working for me. I think it might be either the way moxios.wait is working or more likely react-testing-library wraps an act method around the react act method and is still forwarding it there resulting in the warning. I guess I'll wait this one out for now. Appreciate the help guys. – user5036826 Jun 05 '19 at 14:22

1 Answers1

5

from react 16.9.0 you can use async/await act

Your code should look like this

describe('Benefits', () => {
  it('fetches the list of benefits from an api and populates the benefits table', async() => {
    const { rerender } = render(<Benefits />);

    await moxios.wait(jest.fn);
    await act(async() => {
      const request = moxios.requests.mostRecent()
      await request.respondWith({
        status: 200,
        response: benefits
      });
    });

    expect(document.querySelectorAll('tbody > tr').length).toBe(2)
})

I use jest.fn in moxios.wait because it needs callback function

gare4ka
  • 76
  • 1
  • 4