Testing React Applications
Good React tests give you confidence to change code without fear. The trick is testing what users experience — what renders, what happens on click — rather than how the component is built internally. Tests coupled to implementation break on every refactor and protect nothing.
React Testing Library encodes this philosophy: query the DOM the way a user (or screen reader) would, interact, and assert on visible results.
TL;DR
- Test behavior, not implementation — refactors shouldn't break good tests.
- Use React Testing Library; query by accessible role/label/text.
- Mock the network (MSW), not your own components.
- Write tests that resemble how a user interacts.
Quick Example
Render, interact, assert on what the user sees:
Core Concepts
The testing pyramid
- Unit — pure functions and small units (fast, many).
- Integration — components working together (the sweet spot for UI).
- E2E — full user flows in a real browser (Playwright/Cypress; fewer, slower).
What to test (and not)
Patterns
Async UI
Mock the network with MSW
MSW intercepts requests at the network layer, so your component and data-fetching code run for real.
Comparison: Jest vs Vitest
Common Mistakes
Testing implementation details
Querying by test id when a role works
FAQ
Jest or Vitest?
Vitest for Vite-based projects — it's faster and shares Vite's config, with a Jest-compatible API. Jest remains the standard for older or Create-React-App-era setups. Migrating is usually straightforward because the APIs align.
What should I actually test?
User-visible behavior: what renders for given props, what happens on interaction, and the loading/empty/error states. Skip internal state shape, exact CSS, and third-party internals.
How do I test components that fetch data?
Mock at the network layer with MSW so your real fetching code runs against fake responses. Avoid mocking your own modules — it couples tests to implementation and tests less.
Why query by role instead of test IDs?
Querying by accessible role/label tests the app the way users and assistive tech experience it, and it doubles as a basic accessibility check. Reserve test IDs for when there's genuinely no accessible query.
Related Topics
- React — What you're testing
- Vitest — Fast Vite-native test runner
- Jest — The established test framework
- Playwright — E2E testing
- Accessibility — Why role-based queries help