How to mock a custom hook inside of a React component you want to test?

Why don't you mock the underlying method that makes the api call instead?

For example, if you're retrieving data with fetch(), you mock that instead. That way you can define custom response for that call, which will make testing the hook itself easy.


This question is a few months old, but if you haven't found a good solution, I wrote a package that might help. I went through a similar thought process, including "what if I inject the hooks into the component?" Things got weird.

I basically wanted a connecter to avoid an extra wrapper for presentational components just to test them.

I came up with react-hooks-compose, which lets you keep your hooks and your presenters separate, and test them individually or together: https://www.npmjs.com/package/react-hooks-compose

export const useFetch = () => {
  const [user, setUser] = useState();

  useEffect(() => {
    fetchData('some-url') // <-- Fetches data on mount
      .then(res => setUser(res.data));
  }, []);

  return {user};
}

// composeHooks passes the values from your hooks as props
export const UserPresenter = ({user}) => {
  return <div>You fetched data for: {user.name}</div>;
}

export default composeHooks({ useFetch })(DataPresenter);

Now you don't have to mock the hook, you can just test the presenter with a prop:

it('presents user', () => {
  const { queryByText } = render(<UserPresenter user={{name: 'Mary'}} />); // <-- Named export
  expect(queryByText('Mary')).toBeTruthy();
});

Or, you have the option of a higher-level integration test:

it('fetches data', () => {
  fetchData.mockResolvedValue('Mary');
  const { queryByText } = render(<UserWithData />); // <-- Default export
  expect(queryByText('Mary')).toBeFalsy();
  return wait(() => {
    expect(queryByText('Mary')).toBeTruthy();
  });
});

You can even unit test the hook if you like.


To mock your custom hook using jest.

import * as useCustomHook from '../hooks/useCustomHooks'

const spy = jest.spyOn(useCustomHook, 'default')
spy.mockReturnValue({
name: 'test'
})