# Тестирование домена > Проверка границ и поведения Level 3. ## Связанные правила - [`SLM-L3-TEST-R014`](../../rules/level-3.md#slm-l3-test-r014) - [`SLM-L3-FACTORY-R006`](../../rules/level-3.md#slm-l3-factory-r006) - [`SLM-L3-ASSEMBLY-R010`](../../rules/level-3.md#slm-l3-assembly-r010) ## Принцип размещения Тест находится рядом с модулем-владельцем проверяемой ответственности. У домена нет общей корневой папки `tests/`. | Проверяемая граница | Владелец теста | |---|---| | Предметные сценарии, состояние и ошибки домена | `business` | | Чистая функция бизнес-логики | Соответствующий сегмент `business` | | Реализация порта | Адаптер | | Выбор зависимостей, область жизни и очистка | Модуль в `presets` | | Провайдер, хук и жизненный цикл React | `react` | | Граф нескольких доменов | Модуль-владелец графа | | Полный пользовательский поток | Точка входа сквозного теста приложения | ## Тесты через фабрику Тесты через фабрику являются главным доказательством публичного поведения бизнес-логики. Они импортируют только публичный API `business` и передают управляемые тестовые реализации портов: ```ts import { AUTH_ERROR_CODES, authFactory, isAuthError, } from '@/domains/auth/business' it('maps source failure to domain error', async () => { const requestCode = vi.fn().mockRejectedValue(new Error('Network failed')) const api = authFactory(createAuthTestDeps({ requestCode })) await expect(api.requestPhoneOtp('+79991112233')).rejects.toMatchObject({ code: AUTH_ERROR_CODES.PHONE_OTP_REQUEST_FAILED, }) }) ``` Такой набор тестов проверяет форму публичного API, отсутствие побочных эффектов при создании, успешные и ошибочные сценарии, проверку входных данных, переходы состояния и порядок внешних операций. Тест `business` не использует React, реальный SDK, хранилище или типовую сборку приложения. Если сценарий нельзя проверить без них, техническая зависимость проникла внутрь бизнес-логики. ## Вспомогательная тестовая сборка Закрытая тестовая функция уменьшает повторение, но не является модулем в `presets`: ```ts const { api, ports, state } = createAuthTestHarness({ requestCode }) ``` Она создаёт новый экземпляр для каждого теста, допускает нужные сценарию замены и не экспортируется через рабочую точку входа. Модуль `presets/testing` по умолчанию не создаётся. ## Тесты остальных ролей Тест адаптера проверяет вызванную техническую операцию, переданные данные, преобразование аргументов, результат или ошибку согласно контракту порта и очистку подписки. Он не повторяет преобразование ошибок домена и полный набор предметных сценариев. Тест типовой сборки проверяет полный набор портов, выбор адаптеров, отсутствие ввода-вывода при создании, область жизни экземпляра, передачу операции очистки и границу клиента и сервера. Он не повторяет успешные предметные сценарии. Тест React получает тестовый `AuthApi` и проверяет провайдер, хук доступа, обновление по `subscribe`, очистку после размонтирования и поведение в `StrictMode`. Минимальный интеграционный тест с настоящей фабрикой добавляется только при отдельном риске интеграции. ## Минимальный набор Тест создаётся в ответ на реальный риск, а не ради заполнения каркаса. При этом публичный предметный сценарий требует теста через фабрику, типовая сборка приложения — теста сборки, адаптер с нетривиальным преобразованием данных — теста адаптера, а модуль React с поведением жизненного цикла — теста фреймворка.