🚀 LEVEL UP TO SENIOR:Unlock 500+ Advanced Practical Challenges & Exercises.
🎓 COURSERA PARTNER:Earn professional Google, Meta, and IBM certificates to supercharge your resume.
REFERENCEreact

react Documentation

LOADING ENGINE...

User-Centric Testing with React Testing Library

AI & DATA SCIENCE // react-testing-library

React Testing Library is the modern standard for testing React components, encouraging tests that interact with rendered output the way a real user would, rather than a component's internal implementation details.

Syntax

import { render, screen } from '@testing-library/react';
render(<MyComponent />);
expect(screen.getByText('Hello')).toBeInTheDocument();

Deep Dive Course

React Testing Library's core render() function mounts a component into a real, JSDOM-simulated DOM, and its screen object provides query methods, like getByText, getByRole, and getByLabelText, that find elements the same way a real user would locate them, by visible text, accessible role, or associated label, rather than by internal component names or implementation-specific selectors. Its guiding philosophy, summarized in its own documentation, is that the more your tests resemble the way your software is actually used, the more confidence they can give you — paired with the userEvent library for realistically simulating clicks, typing, and other interactions, and Jest as the underlying test runner and assertion library.

1Understanding User-Centric Testing with React Testing Library

React Testing Library's core render() function mounts a component into a real, JSDOM-simulated DOM, and its screen object provides query methods, like getByText, getByRole, and getByLabelText, that find elements the same way a real user would locate them, by visible text, accessible role, or associated label, rather than by internal component names or implementation-specific selectors. Its guiding philosophy, summarized in its own documentation, is that the more your tests resemble the way your software is actually used, the more confidence they can give you — paired with the userEvent library for realistically simulating clicks, typing, and other interactions, and Jest as the underlying test runner and assertion library.

💡

Prefer getByRole() over getByTestId() or a CSS-selector-based query whenever possible — querying by role most closely reflects how a real user, especially someone using a screen reader, actually perceives and interacts with an element, and it also nudges your markup toward being more accessible.

editor.html
import { render, screen } from '@testing-library/react';
import Greeting from './Greeting';

test('renders a greeting for the given name', () => {
  render(<Greeting name="Ana" />);
  expect(screen.getByText('Hello, Ana!')).toBeInTheDocument();
});
localhost:3000

2Practical Example

Here is a real-world application of User-Centric Testing with React Testing Library showing how it is used in production React code.

editor.html
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import Counter from './Counter';

test('increments the count when the button is clicked', async () => {
  render(<Counter />);
  await userEvent.click(screen.getByRole('button', { name: /increment/i }));
  expect(screen.getByText('Count: 1')).toBeInTheDocument();
});
localhost:3000

3Best Practices

Follow these guidelines when working with User-Centric Testing with React Testing Library:

1. Query rendered elements the way a real user would, by visible text, label, or accessible role, rather than by internal implementation details like a component's name or an arbitrary CSS class

2. Use the userEvent library to simulate realistic user interactions, like typing and clicking, rather than firing low-level synthetic DOM events directly

3. Reserve data-testid attributes and getByTestId() as a last resort, specifically for elements with no other reasonable way to query them as a real user would identify them

⚠️

Tip: Prefer getByRole() over getByTestId() or a CSS-selector-based query whenever possible — querying by role most closely reflects how a real user, especially someone using a screen reader, actually perceives and interacts with an element, and it also nudges your markup toward being more accessible.

editor.html
import { render, screen } from '@testing-library/react';
import Greeting from './Greeting';

test('renders a greeting for the given name', () => {
  render(<Greeting name="Ana" />);
  expect(screen.getByText('Hello, Ana!')).toBeInTheDocument();
});
localhost:3000

Examples

Example 01Basic Usage
import { render, screen } from '@testing-library/react';
import Greeting from './Greeting';

test('renders a greeting for the given name', () => {
  render(<Greeting name="Ana" />);
  expect(screen.getByText('Hello, Ana!')).toBeInTheDocument();
});
Example 02Advanced Example
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import Counter from './Counter';

test('increments the count when the button is clicked', async () => {
  render(<Counter />);
  await userEvent.click(screen.getByRole('button', { name: /increment/i }));
  expect(screen.getByText('Count: 1')).toBeInTheDocument();
});

Best Practices

  • Query rendered elements the way a real user would, by visible text, label, or accessible role, rather than by internal implementation details like a component's name or an arbitrary CSS class
  • Use the userEvent library to simulate realistic user interactions, like typing and clicking, rather than firing low-level synthetic DOM events directly
  • Reserve data-testid attributes and getByTestId() as a last resort, specifically for elements with no other reasonable way to query them as a real user would identify them

Interview Question

Why does React Testing Library deliberately avoid providing an easy way to access a component's internal state directly in a test, unlike Enzyme's shallow-rendering approach?

Hint: Think about what a real end user of the application can and can't see or interact with, and how that maps onto what a test should be allowed to check.

React Testing Library is built around the guiding principle that tests should give confidence the application actually works correctly for real users, and a real user has absolutely no access to, or awareness of, a component's internal state variables, prop names, or how it happens to be broken down into sub-components internally — they only ever see and interact with the actual rendered output: visible text, buttons, form fields, and so on. By deliberately not providing a convenient way to peek at internal state, React Testing Library steers tests toward asserting only on what's actually rendered and interactable, the same things a real user experiences, which means a test genuinely verifies real, user-facing behavior rather than incidental implementation details. This design choice also means such tests remain stable through internal refactoring, since changing how a component is implemented internally, while keeping its rendered behavior identical, shouldn't, and with this approach generally doesn't, break the test at all.

Exercises

MediumPractice using User-Centric Testing with React Testing Library in a real scenario.
View Solution
import { render, screen } from '@testing-library/react';
import Greeting from './Greeting';

test('renders a greeting for the given name', () => {
  render(<Greeting name="Ana" />);
  expect(screen.getByText('Hello, Ana!')).toBeInTheDocument();
});

Frequently Asked Questions

Why does React Testing Library deliberately avoid providing an easy way to access a component's internal state directly in a test, unlike Enzyme's shallow-rendering approach?

React Testing Library is built around the guiding principle that tests should give confidence the application actually works correctly for real users, and a real user has absolutely no access to, or awareness of, a component's internal state variables, prop names, or how it happens to be broken down into sub-components internally — they only ever see and interact with the actual rendered output: visible text, buttons, form fields, and so on. By deliberately not providing a convenient way to peek at internal state, React Testing Library steers tests toward asserting only on what's actually rendered and interactable, the same things a real user experiences, which means a test genuinely verifies real, user-facing behavior rather than incidental implementation details. This design choice also means such tests remain stable through internal refactoring, since changing how a component is implemented internally, while keeping its rendered behavior identical, shouldn't, and with this approach generally doesn't, break the test at all.

Related Functions

jestcomponent-testinghooks-testing