Как SOLID влияет на тестируемость кода?
Принципы S.O.L.I.D
Код по SOLID тестируется дёшево: маленькие единицы с явными зависимостями проверяются изолированно, без сети и базы; и наоборот, трудность теста — ранний сигнал нарушения принципов.
Вклад каждого принципа
- SRP — меньше сценариев на единицу: класс с тремя ответственностями даёт комбинаторный рост подготовки.
- OCP — новая стратегия тестируется отдельно, старые тесты не меняются.
- LSP — позволяет написать контрактные тесты один раз и прогнать их на всех реализациях, включая фейки.
- ISP — тестовый дубль реализует два метода, а не двадцать.
- DIP — даёт швы (seams) для подмены: in-memory репозиторий, фиксированные часы, фейковый HTTP.
/** @typedef {{ now(): Date }} Clock */
class TrialService {
#clock;
/** @param {Clock} clock */
constructor(clock) { this.#clock = clock; }
isExpired(startedAt) {
const ms = this.#clock.now().getTime() - startedAt.getTime();
return ms / 86_400_000 > 14;
}
}
const fixed = { now: () => new Date('2026-01-20') };
new TrialService(fixed).isExpired(new Date('2026-01-01')); // trueЛовушки
- Моки на всё: тесты проверяют порядок вызовов, а не результат, и ломаются при любом рефакторинге. Фейки и проверка состояния устойчивее.
- Интерфейс только ради мока при единственной реализации — иногда проще тестировать с реальной зависимостью через Testcontainers или MSW.
- Test-induced design damage (термин DHH): слои и косвенность исключительно ради тестов.
Коротко для собеседования
Явные зависимости и маленькие модули позволяют тестировать логику без сети и базы, подставляя фейки вроде фиксированных часов. Если тест писать мучительно, это сигнал о нарушении принципов; но и перебор с моками и слоями ради тестов вредит.