Writing Unit Tests for Functional Components0%

Writing Unit Tests for Functional Components

Beginner12 min read•Updated: Jul 11, 2026
Study MaterialsCheatsheet

Writing Unit Tests for Functional Components

1. Anatomy of a Component Unit Test

A standard unit test in React follows the AAA Pattern:

  1. 1
    Arrange: Render the component using render(<MyComponent />) and prepare props or mocks.
  2. 2
    Act: Simulate user interactions (typing, clicking, toggling) using @testing-library/user-event.
  3. 3
    Assert: Verify that the expected DOM elements, text, or callbacks responded correctly.
Output
[Arrange: render(<Counter />)] ──► [Act: user.click(button)] ──► [Assert: expect(text).toHaveTextContent('1')]

2. Complete Example: Testing a Course Card Component

Let's write a comprehensive test suite for an interactive course card:

JSX
// src/components/CourseCard.jsx
import React from 'react';
 
export default function CourseCard({ course, onEnroll }) {
return (
<div className="course-card">
<h3 data-testid="course-title">{course.title}</h3>
<p>{course.description}</p>
<span className="price">${course.price}</span>
<button
type="button"
disabled={course.isSoldOut}
onClick={() => onEnroll(course.id)}
>
{course.isSoldOut ? 'Sold Out' : 'Enroll Now'}
</button>
</div>
);
}

The Vitest Test File:

JSX
// src/components/__tests__/CourseCard.test.jsx
import { describe, it, expect, vi } from 'vitest';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import CourseCard from '../CourseCard';
 
describe('CourseCard Component', () => {
const mockCourse = {
id: 'c-101',
title: 'React.js Mastery',
description: 'Master modern frontend web engineering.',
price: 99,
isSoldOut: false
};
 
it('renders course information correctly', () => {
render(<CourseCard course={mockCourse} onEnroll={vi.fn()} />);
 
// Assert title and price are in the document
expect(screen.getByRole('heading', { level: 3 })).toHaveTextContent('React.js Mastery');
expect(screen.getByText(/Master modern frontend/i)).toBeInTheDocument();
expect(screen.getByText('$99')).toBeInTheDocument();
});
 
it('invokes onEnroll callback with course ID when Enroll button is clicked', async () => {
// vi.fn() creates a mock spy function in Vitest
const handleEnroll = vi.fn();
const user = userEvent.setup();
 
render(<CourseCard course={mockCourse} onEnroll={handleEnroll} />);
 
const enrollButton = screen.getByRole('button', { name: /enroll now/i });
await user.click(enrollButton);
 
// Verify spy function was called exactly once with 'c-101'
expect(handleEnroll).toHaveBeenCalledTimes(1);
expect(handleEnroll).toHaveBeenCalledWith('c-101');
});
 
it('disables the button when the course is sold out', () => {
const soldOutCourse = { ...mockCourse, isSoldOut: true };
render(<CourseCard course={soldOutCourse} onEnroll={vi.fn()} />);
 
const button = screen.getByRole('button', { name: /sold out/i });
expect(button).toBeDisabled();
});
});

3. Why userEvent Over fireEvent

Notice line 27: const user = userEvent.setup(); await user.click(button);.

  • fireEvent.click(): Dispatches a synthetic DOM event instantly without simulating hover, focus, or active state sequences.
  • userEvent.click(): Faithfully simulates what a real human does: moves cursor, fires mouseover, hovers, focuses the element, clicks, and fires blur upon leaving.

Always prefer @testing-library/user-event for interaction testing!


Interactive Quiz

Practice Quiz

Question 1
What is the recommended tool for simulating user clicks and keystrokes in React Testing Library?
Question 2
What Vitest function creates a mock spy function to verify if a callback prop was invoked?
Question 3
What matcher from @testing-library/jest-dom asserts that a button has its HTML disabled attribute active?
Question 4
Why must calls to userEvent methods (like await user.click(...) or await user.type(...)) be awaited?
Question 5
In the AAA testing pattern, what does the "Act" phase represent?
Next Lesson

Simulating User Events and Testing Asynchronous Updates

Continue learning with hands-on practice, examples, and exercises in the upcoming topic.

Practice Quiz

Test your understanding of this lesson with 5 questions. Each question has one correct answer.

PrevNext