Гид по технологиям

Тестирование Next.js приложения с помощью Jest

6 min read Тестирование Обновлено 09 Jan 2026
Тестирование Next.js с Jest — руководство
Тестирование Next.js с Jest — руководство

Мужчина за столом печатает на ноутбуке с кодом на экране.

Почему тесты важны

Основная цель разработки — доставить в продакшн работающее приложение. Тесты помогают сохранить стабильность при добавлении функционала, рефакторинге и обновлениях зависимостей. Даже простые модульные тесты уменьшают количество багов, которые доходят до пользователей, и ускоряют локальную отладку.

Краткое определение: юнит‑тест — автоматизированная проверка логики одной единицы кода (функции или компонента).

Важно: тесты — не замена e2e и мониторинга; это комбинация уровней (unit, integration, e2e), которая даёт наилучшую защиту.

Обзор инструментов

  • Jest — тестовый раннер и фреймворк утверждений. Поддерживает мокинг и снапшоты.
  • @testing-library/react — фокусируется на тестировании поведения компонентов как их использует пользователь.
  • jest-environment-jsdom — окружение для тестов, эмулирующее браузер.

Если вы ещё не выбрали инструменты: Jest + Testing Library — хороший баланс простоты и надёжности для React/Next.js проектов.

Создание простого To-Do приложения в Next.js

Ниже — минимальные шаги для запуска проекта и установки зависимостей (сохраните команды как есть в терминале):

  1. Создать проект:
npx create-next-app@latest test-tutorial
  1. Перейти в директорию проекта:
cd nextjs-test-tutorial
  1. Установить devDependencies:
npm install npm install --save-dev jest @testing-library/react @testing-library/jest-dom jest-environment-jsdom

После этого можно реализовать компонент и написать тесты.

Компонент To-Do (src/pages/index.js)

Откройте файл src/pages/index.js, удалите boilerplate и добавьте следующий код (нижеследующий блок — сам компонент):

import { useState } from "react";  
import styles from "../styles/Home.module.css";  
  
export default function Home() {  
  const [todos, setTodos] = useState([]);  
  const [newTodo, setNewTodo] = useState("");  
  
  const addTodo = () => {  
    if (newTodo.trim() !== "") {  
      const updatedTodos = [...todos, newTodo];  
      setTodos(updatedTodos);  
      setNewTodo("");  
    }  
  };  
  const deleteTodo = (index) => {  
    const updatedTodos = [...todos];  
    updatedTodos.splice(index, 1);  
    setTodos(updatedTodos);  
  };

Этот код использует хук useState для хранения списка задач и поля ввода. Функция addTodo добавляет новую задачу, а deleteTodo удаляет по индексу.

JSX разметка компонента:

return (  
    
       setNewTodo(e.target.value)}       />              
            {todos.map((todo, index) => (           
  •             {todo}           
  •         ))}       
      {todos.map((todo, index) => (         
                   
      ))}     
  );}

Совет по локализации UI: если приложение локализуется, вынесите тексты кнопок и плейсхолдеров в отдельный файл переводов.

Настройка Jest

Создайте в корне файл jest.config.js и добавьте:

const nextJest = require("next/jest");  
const createJestConfig = nextJest({  
  dir: "./",  
});  
const customJestConfig = {  
  moduleDirectories: ["node_modules", "/"],  
  testEnvironment: "jest-environment-jsdom",  
};  
module.exports = createJestConfig(customJestConfig);

В package.json добавьте скрипт тестов:

 "scripts": {  
    "dev": "next dev",  
    "build": "next build",  
    "start": "next start",  
    "lint": "next lint",  
    "test": "jest --watchAll"  
  },

Запуск тестов в режиме watch удобен для локальной разработки. Для CI используйте просто jest –ci или npm test с корректными флагами.

Примеры тестов (папка tests)

Создайте папку tests в корне и файл index.test.js. Импорты:

import Home from "../src/pages/index";  
import "@testing-library/jest-dom";  
import { fireEvent, render, screen, waitFor, act } from "@testing-library/react";

Тест на рендеринг элементов:

describe("Todo App", () => {  
  it("renders the todo app", () => {  
    render();  
    
    expect(screen.getByTestId("todo-input")).toBeInTheDocument();  
    expect(screen.getByTestId("add-todo")).toBeInTheDocument();  
  });  
  
});

Тест добавления задачи:

  it("adds a todo", async () => {  
    render();  
   
    const todoInput = screen.getByTestId("todo-input");  
    const addTodoButton = screen.getByTestId("add-todo");  
    const todoList = screen.getByTestId("todo-list");  
    await act(async () => {  
      fireEvent.change(todoInput, { target: { value: "New Todo" } });  
      addTodoButton.click();  
    });  
  
    await waitFor(() => {  
      expect(todoList).toHaveTextContent("New Todo");  
    });  
  });

Тест удаления задачи:

  it("deletes a todo", async () => {  
    render();  
    
    const todoInput = screen.getByTestId("todo-input");  
    const addTodoButton = screen.getByTestId("add-todo");  
    
    fireEvent.change(todoInput, { target: { value: "Todo 1" } });  
    fireEvent.click(addTodoButton);  
    
    const deleteTodoButton = screen.getByTestId("delete-todo-0");  
    fireEvent.click(deleteTodoButton);  
    
    const todoList = screen.getByTestId("todo-list");  
    await waitFor(() => {  
      expect(todoList).toBeEmptyDOMElement();  
    });  
  });

Запустите тесты:

npm run test

Ноутбук с кодом на экране

Скриншот терминала с успешным тестом ToDo.

Результат Jest в терминале после теста добавления задачи.

Что тестировать в компонентах

  • Рендеринг ключевых элементов (инпут, кнопки, список).
  • Поведение при вводе (onChange) и сабмите (click).
  • Побочные эффекты — вызовы API, сохранение в localStorage (мокируются).
  • Пограничные случаи: пустой ввод, длинные строки, дубли.

Важно проверять не только наличие DOM-элементов, но и поведение, которое важно пользователю.

Частые ошибки и как их избежать

  • Неправильные testid: убедитесь, что testid совпадает в компоненте и тесте.
  • Тесты зависят от внешнего состояния (API, время): используйте мокинг и фикстуры.
  • Утечки таймеров и ассинхронных операций: очищайте моки после тестов и используйте async/await + waitFor.

Стратегии тестирования и когда применять

  • Unit tests: для чистой логики и небольших компонентов — быстрые и стабильные.
  • Integration tests: когда важна связка между компонентами или между компонентом и контекстом/редюсером.
  • E2E tests: для проверки реального поведения приложения в браузере (Cypress, Playwright).

Ментальная модель: “тесты как фильтр“ — быстрые unit‑тесты ловят мелкие баги, integration — архитектурные ошибки, e2e — реальный поток пользователя.

Шпаргалка по Jest и Testing Library

  • Локально: npm run test (watch mode)
  • CI: jest –ci –reporters=default
  • Запретить отдельные блоки: it.only / describe.only при отладке (не пушьте в CI)
  • Очищать моки: afterEach(() => { jest.clearAllMocks(); });

Чек‑лист для ролей

Разработчик:

  • Добавил тесты на новые компоненты.
  • Проверил, что tests не зависят от сети.
  • Запустил npm run test в режиме watch.

Технический лидер:

  • Проверил покрытие ключевой бизнес‑логики.
  • Подтвердил правила о тестid и соглашения по мокингу.

QA инженер:

  • Сопроводил unit-тесты интеграционными или e2e для критичных сценариев.
  • Настроил тесты в CI и прогнал ночные прогоны при необходимости.

Готовый план (Playbook) внедрения тестов в проект

  1. Выделите критичные компоненты (логика оплаты, аутентификация, формы).
  2. Напишите unit‑тесты для бизнес‑логики и компонентов, влияющих на безопасность/данные.
  3. Добавьте integration тесты для связок (API + компонент).
  4. Добавьте базовые e2e сценарии для основных пользовательских потоков.
  5. Настройте CI для прогонов тестов и отправки артефактов при падениях.
  6. Введите правило: коммит невозможен без прохождения локальных тестов (pre-push hook).

Критерии приёмки

  • Все новые фичи покрыты тестами на 70% минимум по логике (процент покрытием может варьироваться в зависимости от проекта).
  • Тесты стабильны и не дают флапов (нестабильных прохождений).
  • CI прерывает релиз при падении тестов на критичных ветках.

Примеры сценариев тестирования и критерии приёмки

  1. Рендеринг компонента:
  • Действие: отрисовать Home.
  • Критерий: input и кнопка Add Todo присутствуют.
  1. Добавление задачи:
  • Действие: ввести текст и нажать Add.
  • Критерий: задача появляется в списке.
  1. Удаление задачи:
  • Действие: добавить задачу, нажать Delete.
  • Критерий: список пуст.
  1. Пустой ввод:
  • Действие: нажать Add с пустым инпутом.
  • Критерий: задача не добавляется.

Обработка ошибок и симуляция падений

Для симуляции ошибок используйте изменённые селекторы или моки, как в примере, где тест падает из‑за изменения data-testid. Это полезно, чтобы убедиться, что тесты действительно проверяют важные места. Но в проде предпочтительнее мокать внешние вызовы, а не ломать селекторы.

Симуляция ошибки теста добавления задачи.

Important: в командной строке и CI держите отдельные конфигурации для jest (например, jest.ci.config.js), если вам нужны разные покрытия или репортеры.

Альтернативные подходы и инструменты

  • Vitest — быстрый тестовый раннер, совместим с Jest API в большинстве случаев.
  • Cypress/Playwright — для e2e тестов с реальным браузером.
  • React Testing Library — остаётся рекомендованным для проверки поведения компонентов.

Когда валится Jest: в очень больших монорепозиториях с сотнями тестов может быть полезна миграция на Vitest ради скорости, но миграция требует проверки совместимости мокинга.

Ментальные эвристики для написания тестов

  • Тестируй поведение, а не реализацию.
  • Малые, независимые тесты лучше крупных интеграционных.
  • Если тест часто ломается — он либо нестабилен, либо проверяет ненадёжный контракт.

Диаграмма выбора типа теста

flowchart TD
  A[Новый функционал] --> B{Влияет ли на критичную бизнес-логику?}
  B -- Да --> C[Unit + Integration + E2E]
  B -- Нет --> D{Чистая презентация или UI?}
  D -- Да --> E[Unit + Snapshot]
  D -- Нет --> F[Unit тесты]
  C --> G[Добавить тесты в CI]
  E --> G
  F --> G

Короткая методология проверки (мини‑метод)

  1. Определить «что важно» в фиче (ключевые действия пользователя).
  2. Написать тесты, которые проверяют именно это поведение.
  3. Мокать внешние зависимости, чтобы тесты были быстрыми.
  4. Запустить локально, затем в CI.

Сниппеты и команды (cheat sheet)

  • Установить зависимости: см. раздел Создание проекта.
  • Запустить тесты в интерактивном режиме: npm run test
  • Запустить один тестовый файл: npx jest path/to/file.test.js
  • Очистить моки: jest.clearAllMocks() в afterEach

Мини‑глоссарий

  • Юнит: единица кода (функция, компонент).
  • Мок: заменитель внешней зависимости в тесте.
  • Снапшот: сохранённое представление компонента для сравнения изменений.

Краткое резюме

Тестирование — обязательная часть разработки продакшн‑готовых приложений. Начните с юнит‑тестов на критичных компонентах, добавьте интеграционные и e2e там, где это оправдано. Jest + Testing Library дают простой и мощный набор для React/Next.js проектов.

Если вам нужно, я могу подготовить готовый набор тестов для вашего репозитория или написать конфигурацию CI для автоматического прогона тестов.

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

RDP: полный гид по настройке и безопасности
Инфраструктура

RDP: полный гид по настройке и безопасности

Android как клавиатура и трекпад для Windows
Гайды

Android как клавиатура и трекпад для Windows

Советы и приёмы для работы с PDF
Документы

Советы и приёмы для работы с PDF

Calibration в Lightroom Classic: как и когда использовать
Фото

Calibration в Lightroom Classic: как и когда использовать

Отключить Siri Suggestions на iPhone
iOS

Отключить Siri Suggestions на iPhone

Рисование таблиц в Microsoft Word — руководство
Office

Рисование таблиц в Microsoft Word — руководство