Click here for the tl;dr
React hooks are an interesting thing to tackle when it comes to testing.
On the one hand, they serve to ultimately provide behavior to components — when a component uses a hook, the closest thing we can test to what the user will see is the DOM output.
This leads us to doing the following to get a meaningful test:
- Writing a "dummy" component that uses our hook
- Rendering that component in our tests
- Making assertions on the DOM throughout
This is ideal, and closely mirrors the behavior that will happen in the browser for any user of our hook. The problem here is that if our hook and/or its use cases are complicated enough, this can get really out of hand. Eventually, we might be spending a lot of time writing these dummy components instead of the tests themselves. And then when we do get to testing it, when something passes/fails, we can't even be confident if it's the hook that's broken or if it's the dummy component.
On the other hand, a hook is an API. In a way, it's more or less a function.
In that case, we'd lean towards testing the code output from the hook, rather than behavior. In the case of hooks, that means testing the
return value of the hook, testing that code gets called correctly when the component renders or props change, etcetera.
This works just fine, and we use @testing-library/react-hooks to make it easier on us.
Still, we're getting further away from the behavior the end user ultimately expects, which brings us away from our ideal standard of high confidence
When testing a hook:
- If it's a one-off for a specific component
- Ask yourself if it really needs to be a hook or not. If it can't be reused, it might be better off just within the component's body itself
- Otherwise, test the hook's behavior within the component's tests
- Try the example component mentioned above
- Make an example component, made just for testing the hook
- Render the component in tests, and assert the hook's behavior by making assertions against the DOM
- If it's clear that the hook and/or the example component are not trivial and fit for this case, skip to step 3
- Use @testing-library/react-hooks to tests the hook's API
- What you'll be testing here is not DOM assertions, but rather the hook's return value
As always with testing, use your best judgment here.