Почему NoSuchBeanDefinedException при выполнении теста интеграции с Spring
У меня есть проект Spring Boot, для которого один из разработчиков написал тесты интеграции с БД в памяти. Вот немного предыстории, прежде чем я задам свой вопрос:
У нас есть следующие модули Maven:
1) постоянство сети: в котором хранятся все сущности и интерфейсы и соответствующие реализации. Все эти классы в упаковке com.mycompany.persistence
,
2) веб-сервисы: в которых хранятся все наши контроллеры отдыха и классы безопасности, связанные с пружиной. Это все в упаковке com.mycompany.services
3) модуль веб-сервисов имеет зависимость модуля maven от модуля веб-персистентности.
4) В модуле веб-сервисов мы определили сервис UserContextServiceImpl
которая является реализацией интерфейса IUserContextService
, Этот сервис в основном инкапсулирует функциональность SecurityContextHolder в Spring, предоставляя только те части информации, относящейся к текущему пользователю, которая необходима через его методы, чтобы везде нам не приходилось использовать SecurityContextHolder. Класс реализации помечается @Service ("userContextService").
5) Интерфейс IUserContextService
находится в постоянном модуле. Есть другой класс AppDependecyHeper
в модуле постоянства, который реализует ApplicationContextAware
и возвращает конкретный экземпляр UserContextService, вызывая appContext.getBean('userContextService')
где appContext
держит ApplicationContext
когда приложение инициализируется.
6) Теперь мы не хотим показывать классы Spring Security в модуле постоянства (по причинам, которые здесь находятся вне контекста) и, следовательно, вышеупомянутой договоренности о получении информации о текущем пользователе через службу путем вызова getBean() method of applicationContext
в классе персистентного слоя AppDependencyHelper
, Эта информация затем используется для обновления полей аудита созданных и модифицированных с помощью EntityListener.
7) Фактическое приложение использует только один ApplicationContext
где и классы персистентного уровня, и веб-контроллеры загружаются в одном единственном весеннем контексте.
8) Все работает нормально, когда приложение работает. Однако, когда наш интеграционный тест запускает вызов appContext.getBean('userContextService')
неудачи и броски NosuchBeanDefinitionException
так как он не может найти компонент с именем 'userContextService'
9) Теперь, наконец, код нашего интеграционного теста (только с соответствующими деталями), который находится в com.mycompany.persistence.embeddeddb
пакет:
@Runwith(SpringJUnit4ClassRunner.class)
@ConfigurationContext
class MyEntityTest{
@Configuration
@ComponentScan("com.mycompany.persistence")
public static class Config{
.....
}
.....//code which eventually gives call to
AppDependencyHelper's method which in turn tries to retrieve userContextService Bean.
}
Теперь вопросы:
1) Почему не удается получить компонент? Я пробовал добавлять com.mycompany.services
как ниже
@ComponentScan({"com.mycompany.persistence","com.mycompany.services"})
но безрезультатно.
2) Что я могу понять, прочитав все, что я получил, это то, что @ContextConfiguration
Нужно предоставить либо файлы XML, либо аннотированные классы, либо WebApplicationInitializer (в моем случае, поскольку у нас только один ApplicationContext), чтобы создать ApplicationContext
из классов @Configuration. Однако я не могу этого сделать, так как Maven начинает жаловаться на круговую зависимость, которая справедливо @Service
аннотированный класс UserContextServiceImpl
находится в модуле веб-сервисов, который уже зависит от модуля веб-персистентности, где написан класс тестового примера.
3) Единственное решение, которое я могу придумать, - это перенести все тестовые классы интеграции в модуль веб-сервисов, чтобы я мог сказать @ConfigurationContext
все классы, из которых он должен создать ApplicationContext
.Я прав?
Последний пункт: ApplicationContext
класс имеет тип GenericApplciationContext
когда я запускаю тесты. Когда я запускаю приложение, очевидно, AnnotatedEmbeddedWebApplicationContext
пожалуйста, дайте мне знать, если есть какое-либо решение этой проблемы?
1 ответ
Из того, что я предполагаю, вы пытаетесь использовать компонент из вашего модуля веб-сервиса в своих интеграционных тестах. Если это так, то да, вы должны перенести свои интеграционные тестовые примеры в свой модуль веб-сервиса - как вы уже предложили в своем вопросе.
РЕДАКТИРОВАТЬ: Вы должны действительно переосмыслить свой дизайн, потому что у вас есть проблема круговой зависимости здесь: web-service
модуль зависит от web-persistence
, но реализация вашего IUserContextService
в web-persistence
находится в web-service
,
Вы, вероятно, должны переместить IUserContextService
(и все ваши интеграционные тесты) на ваш web-service
пакет.