Testing Next.js Applications
Testing is crucial for building reliable Next.js applications. It helps catch bugs early, ensures code quality, and gives you confidence when making changes.
Think of tests as safety nets. They catch problems before they reach your users and make refactoring much safer.
Setting Up Testing
Next.js works great with popular testing frameworks. Here's how to set up Jest with React Testing Library:
npm install --save-dev jest @testing-library/react @testing-library/jest-dom
Create a jest.config.js file:
// jest.config.js
module.exports = {
testEnvironment: 'jsdom',
setupFilesAfterSetup: ['@testing-library/jest-dom'],
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/$1',
},
};
Add test scripts to your package.json:
{
"scripts": {
"test": "jest",
"test:watch": "jest --watch"
}
}
Testing Components
Write tests for your React components using React Testing Library:
// __tests__/Button.test.js
import { render, screen, fireEvent } from '@testing-library/react';
import Button from '@/components/Button';
describe('Button', () => {
it('renders correctly', () => {
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 me</Button>);
fireEvent.click(screen.getByRole('button'));
expect(handleClick).toHaveBeenCalledTimes(1);
});
});
Tests focus on user behavior rather than implementation details.
Testing Pages
Test your pages by rendering them and asserting their content:
// __tests__/Home.test.js
import { render, screen } from '@testing-library/react';
import Home from '@/app/page';
jest.mock('@/lib/api', () => ({
getPosts: jest.fn(() => [
{ id: 1, title: 'First Post' },
{ id: 2, title: 'Second Post' },
]),
}));
describe('Home', () => {
it('renders blog posts', async () => {
render(<Home />);
expect(await screen.findByText('First Post')).toBeInTheDocument();
expect(await screen.findByText('Second Post')).toBeInTheDocument();
});
});
Mock external dependencies like APIs to isolate your tests.
End-to-End Testing
For full application testing, use Cypress or Playwright:
// cypress/e2e/home.cy.js
describe('Home Page', () => {
it('loads successfully', () => {
cy.visit('/');
cy.contains('Welcome to my app');
});
it('navigates to about page', () => {
cy.visit('/');
cy.contains('About').click();
cy.url().should('include', '/about');
});
});
End-to-end tests verify the entire application works together.