Spring контекст грязный после каждого теста интеграции

Недавно я начал работать в качестве фрилансера по моему текущему проекту. Одна из вещей, на которых я набросилась, была неудачная сборка Дженкинса (она провалилась с 8 апреля, за неделю до того, как я начал здесь).

Вообще говоря, вы можете увидеть проблему с ошибками DI в журнале. Первое, что я сделал, - это заставить все тесты работать одинаково, начиная с одного и того же контекста приложения. Они также реализовали свою собственную "насмешливую" вещь, которая, казалось, не работала правильно. После обсуждения с ведущим разработчиком я предложил начать использовать Springockito. (для определенного модуля им нужно было насмехаться за их интеграционное тестирование - устаревшие причины, которые нельзя изменить)

В любом случае, после этого материал начал плохо работать. Многие из beans, которые были издевались над тестом, просто не издевались или не были найдены или что-то еще. Как правило, это не сработало при загрузке контекста приложения, заявив, что тот или иной bean отсутствует.

Я пробовал разные вещи и разные подходы, но, в конце концов, только то, что я больше всего боялся, будет работать: добавьте @DirtiesContext для каждого теста. Теперь сборка maven начинает снова становиться зеленой, тесты начинают делать то, что они должны делать. Но я перезагружаю контекст Spring каждый раз, что занимает время - это все относительно, так как контекст загружается примерно через 1 - 2 секунды.

Обратите внимание на то, что они обновились до Hibernate 4 и, таким образом, до Spring 3.2. Раньше они использовали более старую версию Spring 3. Все тесты работали тогда, и проблема @DirtiesContext не требовалась.

Теперь, что меня больше всего волнует, я не могу сразу придумать объяснение этого странного поведения. Похоже, что контекст Спрингса загрязнен, просто путем запуска теста, который использует @Autowired beans. Не все тесты используют Mocks, так что это не может быть так. Звучит это знакомо кому-нибудь? Имел ли кто-либо опыт тестирования интеграции с (последняя версия) Spring?

В Stackoverflow я нашел этот билет: Как можно проверить "грязный" контекст приложения Spring? Это, похоже, в значительной степени подводит итог поведению, которое я вижу, но дело в том, что мы являемся аутсорсинговыми службами/репозиториями/... и что у нас нет каких-либо разработчиков по этим классам вообще.

Любые мысли?

Спасибо!

Ответ 1

Чтобы ответить на мой собственный вопрос, секрет был в версии Spring. Мы использовали Spring 3.1.3, тогда как я предположил, что они использовали Spring 3.2 (они постоянно говорили о недавнем обновлении версии Spring).

Объяснение было здесь, сообщение в блоге, которое я наткнулся на свою охоту, чтобы зафиксировать его: http://blog.springsource.org/2012/11/07/spring-framework-3-2-rc1-new-testing-features/

И скопируйте копию соответствующей части:

Использование общих factory методов в конфигурации Spring ни в коем случае не является специфическим для > тестирования, а общие factory методы, такие как EasyMock.createMock(MyService.class) или Mockito.mock(MyService.class) часто используются для создания динамических макетов для Spring beans в контексте > тестового приложения. Например, до Spring Framework 3.2 следующая конфигурация может не автоподтвердить OrderRepository в OrderService. Причина в том, что > в зависимости от порядка, в котором beans инициализируется в контексте приложения, > Spring потенциально выводит тип orderRepository bean как java.lang.Object > вместо com.example.repository.OrderRepository.

Итак, как я решил эту проблему? Ну, я сделал следующие шаги:

  • создать новый модуль maven
  • отфильтруйте те тесты, которые требовали насмешек. Все тесты, не связанные с фальсификацией, будут нормально выполняться в сборке Spring в отдельном прогоне Failsafe (я создал базовый пакет "clean" и отсортировал их так)
  • Поместите все издевавшиеся тесты в базовый пакет под названием "mocked" и выполните дополнительный запуск в Failsafe для издевавшихся тестов.
  • Каждый из насмешанный тест использует Springockito для создания макетов. Я также использую аннотации Springockito, чтобы просто сделать @ReplaceWithMock на месте. Каждый издеваемый тест затем аннотируется с @DirtiesContext, поэтому контекст загрязняется после каждого теста, а контекст Spring повторно вводится с каждым тестом.

Единственное разумное объяснение, которое я мог бы дать, заключается в том, что контекст эффективно загрязняется, потому что существует инфраструктура (Springockito), которая берет на себя управление Spring beans из структуры Spring. Я не знаю, правильно ли это, но это лучшее объяснение, которое я мог бы придумать. Это, по сути, определение грязного контекста, поэтому мы должны обозначить его как грязный.

Используя эту стратегию, я снова создал и запускал, и все тесты работают нормально. Это не идеально, но он работает, и он последователен.