HuntExams Academy logo
ReactAdvanced#testing

How do you test React components?

Answer

Render with React Testing Library and assert on what the user sees, querying by role or label rather than implementation details, and use userEvent for interactions.

Example

render(<Login />);
await userEvent.type(screen.getByLabelText('Email'), 'a@b.com');
await userEvent.click(screen.getByRole('button', { name: /log in/i }));
expect(screen.getByText(/welcome/i)).toBeInTheDocument();

Detailed explanation

I test React components by checking observable behaviour: what users can see, which controls they can operate, and how the interface changes after an action. React Testing Library is useful because it encourages tests against the rendered DOM rather than component instances, internal state, or private functions. Jest or Vitest typically runs the tests and provides mocks and assertions, while a DOM environment such as jsdom supports rendering. The jest-dom matchers add readable assertions such as toBeInTheDocument, toBeDisabled, and toHaveAccessibleName.

A typical test renders the component with realistic props and any required providers, finds a control through an accessible query, performs an interaction, and checks the outcome. Prefer getByRole with an accessible name, or getByLabelText for labelled inputs, over CSS selectors and test IDs. These queries make tests closer to how users identify controls and can expose some accessibility problems, although they do not replace accessibility testing. Create a user with userEvent.setup(), then await user.type() and user.click(). userEvent models interaction sequences more realistically than manually dispatching a single event with fireEvent.

Handle asynchronous behaviour explicitly. getBy queries are for elements expected immediately; findBy queries return promises and retry until a matching element appears. queryBy is useful for asserting absence. For a login request, enter the credentials, click Log in, and use await screen.findByText(/welcome/i) if the success message appears asynchronously. Use waitFor when an assertion needs retrying, and waitForElementToBeRemoved for a visible loading indicator that disappears. React Testing Library helpers generally handle React's act coordination; arbitrary delays usually hide synchronization problems rather than solve them.

Choose test cases around meaningful states: initial rendering, validation errors, loading, success, failure, and disabled controls. For API-backed components, mock the network boundary with a tool such as MSW instead of replacing every child or hook. Wrap components with real routing or context providers where practical, and keep tests isolated by resetting mutable test state and request handlers. Interviewers look for reliable behaviour-focused coverage, sensible mocking boundaries, and awareness that DOM tests cannot prove browser layout or complete application flows; browser-based end-to-end tests cover those gaps.

Key points to remember

  • Render with React Testing Library using realistic props and required providers.
  • Prefer accessible role and label queries over selectors or implementation details.
  • Use userEvent.setup() and await user interactions.
  • Choose getBy for immediate presence, findBy for asynchronous presence, and queryBy for absence.
  • Cover meaningful UI states and mock external boundaries rather than component internals.

Common mistakes candidates make

  • Asserting internal state, hook calls, or large snapshots instead of user-visible behaviour.
  • Forgetting to await interactions or asynchronous UI updates, then adding fixed delays to make tests pass.
  • Over-mocking children and providers so the test no longer exercises realistic component behaviour.

Likely follow-up questions

When would you use fireEvent instead of userEvent?

Prefer userEvent for normal typing, clicking, and keyboard interactions because it simulates fuller interaction sequences. Use fireEvent when you need to dispatch a specific low-level event that userEvent does not conveniently support.

How do you test a component that fetches data?

Render it with the required providers and intercept its requests using MSW with controlled responses. Assert loading, success, and failure behaviour, using asynchronous queries to wait for the resulting UI.

Do React Testing Library tests replace end-to-end tests?

No: they efficiently verify component behaviour and integration in a controlled environment. End-to-end tests run critical flows in a real browser and can reveal issues involving navigation, browser behaviour, and backend integration.

Interview tip: Explain the render–query–interact–assert flow with a login example, then mention asynchronous assertions and your mocking boundary.

Related Interview Questions

1
ReactIntermediate#accessibility

What accessibility basics should a React component follow?

Open
2
ReactAdvanced#context#performance

How do you avoid unnecessary re-renders from context?

Open
3
ReactBeginner#fundamentals

What is React and why use it?

Open