Testing Patterns
Unit tests, integration tests, E2E tests, and mock strategies.
Overview
Comprehensive testing ensures reliability and prevents regressions.
Key Concepts
- Unit Tests — Test individual functions
- Integration Tests — Test component interactions
- E2E Tests — Test complete user flows
- Mocking — Mock external dependencies
- Snapshot Testing — Detect UI changes
Code Examples
// Unit test
// lib/__tests__/utils.test.js
import { formatPrice, slugify } from '../utils';
describe('formatPrice', () => {
it('formats USD correctly', () => {
expect(formatPrice(1999, 'USD')).toBe('$19.99');
});
it('formats EUR correctly', () => {
expect(formatPrice(1999, 'EUR')).toBe('€19.99');
});
});
// Component test
// components/__tests__/Button.test.jsx
import { render, screen, fireEvent } from '@testing-library/react';
import Button from '../Button';
describe('Button', () => {
it('renders with text', () => {
render(<Button>Click me</Button>);
expect(screen.getByRole('button')).toHaveTextContent('Click me');
});
it('calls onClick when clicked', () => {
const handleClick = jest.fn();
render(<Button onClick={handleClick}>Click</Button>);
fireEvent.click(screen.getByRole('button'));
expect(handleClick).toHaveBeenCalledTimes(1);
});
it('is disabled when disabled prop is true', () => {
render(<Button disabled>Click</Button>);
expect(screen.getByRole('button')).toBeDisabled();
});
});
// Integration test
// pages/__tests__/Products.test.jsx
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import Products from '../products';
describe('Products page', () => {
it('displays products after loading', async () => {
global.fetch = jest.fn().mockResolvedValue({
json: () => Promise.resolve([{ id: 1, name: 'Test Product' }])
});
render(<Products />);
await waitFor(() => {
expect(screen.getByText('Test Product')).toBeInTheDocument();
});
});
});
Practice
Write a comprehensive test suite for a Next.js page with form handling.