← Back to React Course | Chapter 12: Testing React Applications | Lesson 2 of 9

Setting Up React Testing Library

React Testing Library is like a robot pretending to be a real user — it clicks buttons and reads text on the screen the same way a person would, instead of poking at your code's internals.

Rendering a Component for Testing

React Testing Library's render() function mounts a component into a virtual, jsdom-based DOM specifically for the test, similar to how ReactDOM.createRoot().render() mounts it in a real browser. Once rendered, you can query and interact with it as if it were on a real page.

Note: Each test typically calls render() fresh at the start, giving every test a clean, isolated component instance.

Warning: render() uses jsdom (a simulated browser environment in Node), not a real browser — some browser-specific behaviors may not be perfectly replicated.

Example: Rendering a Component for Testing

markup
// Run in your local React project (npm install required)
import { render, screen } from '@testing-library/react';
import Greeting from './Greeting';

test('renders greeting', () => {
  render(<Greeting name="Asha" />);
  expect(screen.getByText('Hello, Asha')).toBeInTheDocument();
});

⚠️ This example uses an npm package with no CDN build available here — run this in your local React project.

Querying with the screen Object

After rendering, the screen object provides methods like getByText, getByRole, and getByLabelText to find elements in the rendered output, mirroring how a user would identify things — by visible text or accessible role, not by internal implementation details.

Note: getByRole (e.g. getByRole(button, { name: Submit })) is Testing Library's most recommended query — it reflects real accessibility semantics.

Warning: getBy* queries throw an error if no match is found (or more than one matches) — use queryBy* instead when you expect something might legitimately not exist.

Example: Querying with the screen Object

markup
// Run in your local React project (npm install required)
import { render, screen } from '@testing-library/react';
import LoginButton from './LoginButton';

test('finds the login button by role', () => {
  render(<LoginButton />);
  const button = screen.getByRole('button', { name: 'Log In' });
  expect(button).toBeInTheDocument();
});

⚠️ This example uses an npm package with no CDN build available here — run this in your local React project.

Why RTL's Philosophy Matters

Testing Library is deliberately designed to discourage testing implementation details (like a component's internal state or specific class names), and instead encourage testing what a real user actually experiences — visible text, accessible roles, and interactive behavior. This makes tests more robust against internal refactors.

Note: If you're tempted to reach for a CSS-selector-based query, check first whether a role, label, or text-based query would work — it usually does and is more resilient.

Warning: Overusing data-testid attributes as the primary way to find elements skips the accessibility benefits that role/label-based queries encourage naturally.

Example: Why RTL's Philosophy Matters

markup
// Run in your local React project (npm install required)
// Prefer this (resilient to internal refactors):
screen.getByRole('button', { name: 'Submit' });

// Over this (brittle, tied to implementation):
// container.querySelector('.btn-submit-primary-v2');
Common Mistakes
  1. Using enzyme-style queries (looking for component internals) instead of Testing Library's user-facing queries.
  2. Not wrapping state updates that happen after user events in await, causing flaky tests.
  3. Querying by CSS class or test ID as the first choice, when a more accessible query (role, label text) usually exists and is preferred.
Chapter Summary
  • React Testing Library (RTL) renders real components into a virtual DOM for testing, then queries them the way a user would.
  • render() mounts a component; screen provides query methods to find elements.
  • RTL's philosophy: 'the more your tests resemble the way your software is used, the more confidence they can give you'.
  • It's commonly paired with Jest or Vitest as the underlying test runner.
Browser Support

Requires npm install @testing-library/react — runs in a Node test environment, not this browser sandbox.

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.