Как ограничить класс Spring @Configuration созданием экземпляров только альтернативных служб?

#java #spring

#java #spring

Вопрос:

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

 @Configuration
public class SpringDevTestConfiguration {

    @Bean
    @Profile("unittest")
    public DatabaseService databaseService() {
        // this one is needed for the test
        return new TestDatabaseServiceImpl();
    }

    @Bean
    @Profile("unittest")
    public RobotControlService robotControlService() {
        // Why should I do this on every service?
        return new RobotControlServiceImpl();
    }

... etc.
  

Подавляющему большинству компонентов не нужны тестовые альтернативы, поэтому мы хотим, чтобы по умолчанию один, который существует и выбирается во время выполнения. Но всякий раз, когда в систему добавляется новый компонент, мы должны добавлять его во все @Configuration классы, иначе мы получаем исключение « NoSuchBeanDefinitionException : нет подходящего компонента типа …». Это слишком много шаблонного кода для возврата классов Impl и не позволяет нам создавать классы реализации, защищенные от пакетов (потому что класс конфигурации должен иметь возможность создавать их экземпляры).

Я попытался добавить @ComponentScan в класс, но это приводит к BeanDefinitionOverrideException . Если я разрешу переопределение компонента с:

 spring.main.allow-bean-definition-overriding=true
  

… тогда я получаю NoUniqueBeanDefinitionException из-за множества реализаций службы базы данных.

Я уверен, что я, должно быть, что-то упускаю. Как я могу создать короткий, простой @Configuration класс, который создает экземпляры только тех тестовых реализаций, которые мне нужны для теста, а затем позволяет автоматически обнаруживать другие службы без их явного создания?

Комментарии:

1. Рассмотрите возможность использования Mockito вместо этого.

2. Спасибо, но я спрашиваю о том, как прекратить перечислять (сотни) не издевающихся служб.

3. Можете ли вы показать минимальный пример проекта? Хотя, вероятно, необходимо иметь некоторое дублирование компонентов, нетипично добавлять его ко «всем @Configuration классам». Обычно конфигурация вашего приложения выполняется таким образом, что в файлах конфигурации yml / xml можно переопределять только то, что отличается между профилями (dev, prod, test и т.д.). В этом случае, если у каждого отдельного компонента есть определенная тестовая реализация, ваша тестовая настройка, вероятно, не очень значима.

4. Еще немного информации… Я вижу другие @Configuration аннотированные классы в системе только с одним-пятью @Bean методами (некоторые издевались, некоторые нет). Но в данном случае это действительно интеграционный тест, который генерирует десятки тысяч тестов с использованием @TestFactory (из JUnit 5) тысяч отдельных классов бизнес-логики. Поскольку они являются интеграционными тестами, создаваемыми динамически, им требуется большинство реальных сервисов, доступных при их запуске. Похоже, что у Spring нет способа легко использовать службы проверки компонентов по умолчанию.