← Back to React Testing Library Mastery
Intermediate16 min read

Testing Hooks

Test custom hooks with renderHook and act from React Testing Library.

renderHook

@testing-library/react renderHook executes hook in test component wrapper. result.current accesses return value; rerender updates props.

Test hooks directly when logic complex; otherwise test through component using hook for user-facing confidence.

import { renderHook, act } from "@testing-library/react";
import { useCounter } from "./useCounter";

test("increments", () => {
  const { result } = renderHook(() => useCounter());
  act(() => result.current.increment());
  expect(result.current.count).toBe(1);
});

act with Hooks

State updates from hook methods need act wrapper when triggered outside userEvent. renderHook batches updates; still wrap manual dispatches.

Async hooks: await waitFor after act triggering fetch inside hook.

await act(async () => {
  await result.current.loadData();
});
await waitFor(() => expect(result.current.data).not.toBeNull());

Providers for Context Hooks

Hooks depending on Context need wrapper with Provider in renderHook options. Same pattern as component custom render.

Pass initial prop changes via rerender({ initialProps: { userId: "2" } }) for parameterized hook tests.

const wrapper = ({ children }) => (
  <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
);

renderHook(() => useUsers(), { wrapper });

Testing Effects

Assert side effects via mock callbacks or MSW request counts—not by reading effect internals. waitFor confirms effect completed observable outcome.

Cleanup effects: unmount hook wrapper and assert subscription removed if mock tracks dispose.

  • Avoid testing useEffect dependency array directly
  • Simulate window resize or online/offline for responsive hooks
  • useLayoutEffect same testing approach as useEffect

When Not to testHook

Thin hooks wrapping useState with no logic—test via component. Hooks tightly coupled to UI presentation belong in component tests.

Extract pure functions from hooks for easy unit test without renderHook when calculation heavy.

  • @testing-library/react-hooks merged into main package
  • Vitest compatible with same renderHook API
  • Strict mode double mount may invoke effect twice in dev—assert idempotent

Get In Touch


Ready to discuss your next project? Drop me a message.