Для чего нужна инверсия управления (IoC) в Spring
Что проверяют
Понимаете ли вы, откуда в тестовом фреймворке берутся объекты и почему их не создают через new. Для автоматизатора на Java это практический вопрос: Spring часто собирает клиенты API, page objects и конфигурацию стендов. Следом спрашивают, чем IoC отличается от DI и что такое scope бина.
Как отвечать
Инверсия управления значит, что объект не создаёт свои зависимости сам, их создаёт и передаёт контейнер. В Spring это ApplicationContext: он читает конфигурацию, создаёт бины и связывает их между собой. DI (внедрение зависимостей) это основной способ реализовать IoC.
Зачем это тестировщику:
- подмена зависимостей: класс получает
PaymentClientчерез конструктор, значит, в тесте его легко заменить заглушкой. Для этого есть@MockitoBeanиз Spring Framework 6.2, он заменил@MockBean, объявленный устаревшим в Spring Boot 3.4; - стенды: адреса, логины и таймауты приходят через
@Valueили@ConfigurationProperties, а профили (@Profile,spring.profiles.active=stage) переключают окружение без правки кода; - единая сборка фреймворка: WebDriver, HTTP-клиенты, доступ к базе и брокеру описаны один раз и внедряются в шаги. С Cucumber это делает модуль
cucumber-spring; - кеш контекста: Spring TestContext переиспользует поднятый контекст между тестовыми классами с одинаковой конфигурацией, и прогон заметно ускоряется.
Покажите, что знаете про внедрение через конструктор: поле можно сделать final, класс создаётся и без Spring, а при единственном конструкторе @Autowired писать не нужно.
Где спотыкаются
Не помнят, что scope по умолчанию singleton. Один WebDriver на весь контекст при параллельном запуске означает, что тесты кликают в одном браузере. Здесь нужен prototype или свой scope на поток.
Ставят @DirtiesContext где попало и собирают разные наборы моков в каждом классе. Каждая новая комбинация поднимает свой контекст, и прогон растягивается.
Внедряют через поля с @Autowired. Такой класс не создать в обычном юнит-тесте без контекста, а зависимости не видны в сигнатуре.