reactjsreact-hooksreact-testing-library

React Hook testing with renderHook


I want to test the state update of the component using renderHook from @testing-library/react-hooks, which let us render the hook in the same way as we do in a react functional component. Just want to know, is this only applicable for custom hooks, because the state is not getting changed when I am trying this for testing a component

it('test count update', () => {
    const { result } = renderHook(() => useState({ count: 0 }));
    const [state, setState] = result.current;
    const wrapper = mount(<ComponentToTest />);

    act(() => {
       wrapper.find('button').simulate('click');
    })
    expect(state).toBe({ count: 1 });
})

getting an error since the count is not getting updated and still remains 0

Can anyone please help

enter image description here


Solution

  • From the docs:

    Renders a test component that will call the provided callback, including any hooks it calls, every time it renders.

    renderHook is used to test the hook itself, not a component that uses that hook. renderHook itself renders a test component; you cannot directly test or verify a hook's result by rendering a component that happens to use that hook.

    In your case, you're just testing useState, which you can absolutely do with renderHook:

    import { useState } from 'react'
    import { renderHook, act } from '@testing-library/react'
    
    it('test count update', async () => {
      const { result } = renderHook(() => useState({ count: 0 }))
      const [state, setState] = result.current
      act(() => setState({ count: state.count + 1 }))
      const [nextState, _] = result.current
      expect(nextState.count).toBe(1)
    })
    

    But that seems kind of pointless; we know useState works.

    If you want to test a component that uses useState (or any hook), you need to render the component itself and assert the result of that hook in the rendered component. E.g.

    it('test count update', () => {
        const wrapper = mount(<ComponentToTest />);
    
        act(() => {
           wrapper.find('button').simulate('click');
        })
        // assuming the result is rendered in a span with a classname of 'result'
        expect(wrapper.find('span.result').text()).toBe('1');
    })