Jest · Unit tests that survive refactors
How do you test React components with Jest?
Short answer
Render the component with Testing Library, interact with userEvent, and assert on what the user sees. Mock the network and timers at the boundary rather than replacing the component's own hooks.
A component test should survive a refactor from hooks to context or from local state to a store. That means asserting on rendered output and interaction, not on internal calls. Jest supplies the runner and jsdom supplies the DOM; Testing Library supplies the user-centric queries.
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
test("submits the form and shows a confirmation", async () => {
const user = userEvent.setup();
const onSubmit = jest.fn().mockResolvedValue(undefined);
render(<SignupForm onSubmit={onSubmit} />);
await user.type(screen.getByLabelText("Email"), "asha@example.com");
await user.click(screen.getByRole("button", { name: "Sign up" }));
expect(onSubmit).toHaveBeenCalledWith("asha@example.com");
expect(await screen.findByRole("status")).toHaveTextContent("Check your inbox");
});What to assert
- Rendered text, labels, roles and visible states
- Calls to injected callbacks or API functions
- Loading, error and empty states after async work
- Keyboard and focus behaviour where it matters
- Not internal state names or whether a specific hook ran
Mock the network with MSW or a fetch stub, not the component's data hook. If a component is hard to test through the UI, that often signals a missing accessible label or too much logic in the component. Extract the logic into a pure function or a custom hook and test it separately.
render relies on automatic cleanup in typical setups. If you see duplicated elements across tests, check that cleanup runs between cases or call it explicitly in afterEach.Follow-ups you should expect
Interviewers use these to check whether the first answer was understanding or memorisation.
- 1Why should you avoid mocking a component's own hook?
- 2How do you test loading and error states?
- 3When do you extract logic out of a component for testing?
- 4Why is getByRole preferred over getByTestId?
Say it in the interview
I render the component and interact with it the way a user would, using role, label and text queries with userEvent. I assert on visible outcomes and on calls to injected dependencies. I mock the network at the boundary so the component's real data handling runs. If a component is hard to test through its UI, I take that as a design or accessibility signal rather than reaching into its internals.
Use this as a model, not a script. Saying it in your own words is what makes it survive follow-up pressure.
Related questions
Reading is step one
Now say it out loud.
Understanding an answer and delivering it under pressure are different skills. Rehearse this topic in a live Jest mock interview and get scored feedback on depth, clarity and confidence.