Секрет первый: полное использование встроенного инструментария Testing Module. NestJS предоставляет пакет `@nestjs/testing`, центральным элементом которого является `Test.createTestingModule()`. Мастера не просто создают модуль, они виртуозно им управляют. Ключевая техника — это точечное переопределение провайдеров с помощью `.overrideProvider()` и `.overrideGuard()` / `.overrideInterceptor()` и т.д. Вместо того чтобы поднимать весь тяжеловесный модуль со всеми его внешними зависимостями (база данных, почтовые сервисы, сторонние API), вы заменяете их на контролируемые моки или заглушки. Это позволяет тестировать, например, сервис в полной изоляции, но в его родном NestJS-контексте, с работающим внедрением зависимостей. Всегда очищайте состояние после каждого теста, используя `module.close()`.
Секрет второй: глубокая стратегия мокирования с использованием `jest.fn()` и кастомных провайдеров. Простых `jest.mock()` на уровне модуля часто недостаточно. Мастера создают детализированные mock-объекты для репозиториев, сервисов и клиентов. Например, для TypeORM-репозитория создается объект с методами `find`, `save`, `create`, которые являются `jest.fn()`. Это позволяет не только подменять реализацию, но и **утверждать (assert) о взаимодействиях**: проверить, что сервис действительно вызвал `repository.save` с конкретными аргументами. Для сложных зависимостей используют кастомные провайдеры с фабриками, которые возвращают сконфигурированные моки прямо в `TestingModule`.
Секрет третий: многоуровневое тестирование — от модульного до интеграционного с реальной БД. Мастера выстраивают пирамиду тестов:
- **Изолированные модульные тесты для сервисов (Services) и пайпов (Pipes):** Здесь мокируются все зависимости. Тестируется чистая бизнес-логика.
- **Интеграционные тесты для контроллеров (Controllers):** Используется `TestingModule`, где реальный контроллер инжектит mocked-сервисы. Тестируется корректность маршрутов, валидация входящих данных (через DTO и пайпы), преобразование ответов. Для симуляции HTTP-запросов используют `supertest` или встроенный `NestFastifyApplication`.
- **Тесты "провайдеров" в широком смысле (Guard, Interceptor, Middleware, Filter):** Их тестируют как в изоляции, так и в контексте запроса к контроллеру, чтобы убедиться в правильности их срабатывания и порядка выполнения.
- **E2E-тесты с изолированной тестовой базой данных:** Это высший пилотаж. С помощью `Test.createTestingModule()` поднимается почти настоящее приложение, но провайдер `TypeOrmModule` или `MongooseModule` подключается к временной БД (например, SQLite в памяти, локальный Docker-контейнер с PostgreSQL или специальная тестовая схема). Перед каждым тестовым прогоном база очищается и заполняется фикстурами. Это самые медленные, но и самые надежные тесты, проверяющие взаимодействие всех слоев.
Секрет пятый: автоматизация и CI/CD-интеграция. Набор из тысяч тестов бесполезен, если его нельзя быстро и надежно запустить. Мастера настраивают скрипты `npm run test:unit`, `npm run test:int`, `npm run test:e2e`. Они конфигурируют Jest для параллельного запуска тестов, генерации отчетов о покрытии (coverage) в формате lcov для интеграции с SonarQube. В CI/CD-пайплайне (GitHub Actions, GitLab CI) E2E-тесты запускаются на этапе, где развернута свежая тестовая среда. Используются инструменты для управления состоянием базы данных между прогонами (миграции, сиды).
Секрет шестой: фокус на тестировании граничных случаев и ошибок. Хорошо протестировать успешный сценарий (`200 OK`) — это только половина дела. Мастера уделяют особое внимание тестированию обработки ошибок: корректно ли работают `Exception Filter`, возвращают ли они нужный HTTP-статус и формат тела? Тестируются сценарии с невалидными входными данными (проверка `ValidationPipe`), случаи, когда сервис кидает `NotFoundException` или `ForbiddenException`. Тестируются guard'ы на предмет корректного запрета доступа.
Тестирование NestJS — это искусство баланса между изоляцией и интеграцией, между скоростью выполнения тестов и их надежностью. Используя встроенный инструментарий для точечного мокирования, выстраивая многоуровневую пирамиду тестов и интегрируя процесс в CI/CD, вы превращаете тестирование из рутины в мощный механизм обеспечения качества, который позволяет с уверенностью развивать сложное серверное приложение. Это и есть уровень мастера.
Комментарии (13)