React Testing — Vitest and React Testing Library
Advertisement
React Testing — Vitest and React Testing Library
Testing React components ensures reliability and prevents regressions.
- React Testing — Vitest and React Testing Library
- Setup
- Basic Test
- User Interactions
- Mocking
- Real-World: Component Test
- FAQ
Setup
npm install -D vitest @testing-library/react @testing-library/jest-dom
Basic Test
import { test, expect } from 'vitest'
import { render, screen } from '@testing-library/react'
import { Counter } from '@/components/counter'
test('renders counter', () => {
render(<Counter />)
expect(screen.getByText(/count/i)).toBeInTheDocument()
})
test('increments on button click', () => {
render(<Counter />)
const button = screen.getByRole('button', { name: /increment/i })
button.click()
expect(screen.getByText('1')).toBeInTheDocument()
})
User Interactions
import { userEvent } from '@testing-library/user-event'
test('form submission', async () => {
const user = userEvent.setup()
render(<LoginForm />)
const input = screen.getByLabelText(/email/i)
await user.type(input, 'test@example.com')
const button = screen.getByRole('button')
await user.click(button)
expect(screen.getByText(/logged in/i)).toBeInTheDocument()
})
Mocking
import { vi } from 'vitest'
test('calls API on submit', async () => {
const mockFetch = vi.fn().mockResolvedValue({
json: () => Promise.resolve({ id: 1 })
})
global.fetch = mockFetch
render(<Form />)
// ... test form submission
expect(mockFetch).toHaveBeenCalled()
})
Real-World: Component Test
test('todo list', async () => {
const user = userEvent.setup()
render(<TodoList />)
// Add a todo
const input = screen.getByPlaceholderText(/add todo/i)
await user.type(input, 'Learn testing')
const addButton = screen.getByRole('button', { name: /add/i })
await user.click(addButton)
// Verify todo appears
expect(screen.getByText('Learn testing')).toBeInTheDocument()
// Delete todo
const deleteButton = screen.getByRole('button', { name: /delete/i })
await user.click(deleteButton)
expect(screen.queryByText('Learn testing')).not.toBeInTheDocument()
})
FAQ
Q: Should I test implementation details? A: No, test behavior instead. Use React Testing Library, not shallow render.
Q: How much coverage do I need? A: Aim for 80% coverage of critical paths, not 100%.
Q: Is E2E testing better than unit tests? A: Both are needed. Unit tests for components, E2E for workflows.
Good testing practices build confidence in your React code.
Advertisement