reactjs
/

React Testing – Vitest & React Testing Library

Last Sync: Today

On this page

5
0%
5 min read
Remaining
5 minleft

Click any section to jump — progress syncs automatically

reactjs

React Testing – Vitest & React Testing Library

The Philosophy of React Testing

In modern React development, we follow the principle: 'The more your tests resemble the way your software is used, the more confidence they can give you.' Instead of testing internal implementation details (like state values), we test the outcomes that the user sees and interacts with.

The Testing Stack (2026)

  • Vitest: A blazing fast unit test framework powered by Vite. It is the modern replacement for Jest.
  • React Testing Library (RTL): Provides utilities to work with React components in a way that encourages good testing practices.
  • Mock Service Worker (MSW): The gold standard for mocking API calls by intercepting requests at the network level.
  • Playwright: Used for End-to-End (E2E) testing to simulate full user flows in real browsers.

Writing Your First Component Test

A standard test follows the AAA Pattern: Arrange (set up the component), Act (simulate user interaction), and Assert (verify the outcome).

React JSXRead-only
1
import { render, screen, fireEvent } from '@testing-library/react';
import { describe, it, expect } from 'vitest';
import Counter from './Counter';

describe('Counter Component', () => {
  it('increments the count when the button is clicked', () => {
    // Arrange
    render(<Counter />);
    const button = screen.getByRole('button', { name: /increment/i });

    // Act
    fireEvent.click(button);

    // Assert
    expect(screen.getByText('Count: 1')).toBeInTheDocument();
  });
});

Testing Async Logic & API Mocks

When testing components that fetch data, use findBy queries (which return promises and retry until the element appears) instead of getBy.

React JSXRead-only
1
// Testing a user list that loads from an API
it('renders a list of users', async () => {
  render(<UserList />);
  
  // findBy queries wait for the element to appear (default 1000ms)
  const userItem = await screen.findByText('Kishore Kumar');
  expect(userItem).toBeInTheDocument();
});

Testing Strategy Comparison

Test TypeToolScopeSpeed
UnitVitestIndividual functions/hooksInstant
IntegrationRTL + VitestGroups of components working togetherFast
E2EPlaywrightFull app in a real browserSlow
StaticESLint / TSSyntax and type checkingReal-time

Try it yourself

import React, { useState } from 'react';

// Imagine we are testing this Toggle component
function Toggle() {
  const [isOn, setIsOn] = useState(false);
  return (
    <div>
      <p>Status: {isOn ? 'Active' : 'Inactive'}</p>
      <button onClick={() => setIsOn(!isOn)}>
        Toggle State
      </button>
    </div>
  );
}

// This is how a Vitest + RTL test would look like:
/*
  test('toggles status on click', () => {
    render(<Toggle />);
    const button = screen.getByText('Toggle State');
    fireEvent.click(button);
    expect(screen.getByText('Status: Active')).toBeInTheDocument();
  });
*/

export default Toggle;

Test Your Knowledge

Q1
of 3

Which Testing Library query should you use for elements that aren't immediately in the DOM?

A
getBy
B
queryBy
C
findBy
D
selectBy
Q2
of 3

What does the 'AAA' acronym stand for in testing?

A
Action, Assertion, Application
B
Arrange, Act, Assert
C
Always Apply Access
D
Analysis, Architecture, Action
Q3
of 3

What is the main advantage of Vitest over Jest in a Vite project?

A
It supports more languages
B
It uses the same configuration and transform logic as Vite, making it faster
C
It doesn't require any code
D
It can only test CSS

Frequently Asked Questions

Why use 'screen.getByRole' instead of 'container.querySelector'?

getByRole tests for accessibility. If a user can't find a button because it lacks a label or role, your test should fail. querySelector tests implementation, which can break if you change a class name.

What is 'Snapshot Testing'?

It records the rendered output of a component and compares it to future versions. It's useful for catching unexpected UI changes but can be brittle if overused.

How do I test hooks directly?

Use renderHook from @testing-library/react. It allows you to call the hook and assert its return values without building a dummy component.

Previous

react lazy loading

Next

react error boundaries

Related Content

Need help?

Explore our comprehensive docs or start a chat with our tech experts.