Как заставить Spring автоматически связать тестовый класс интеграции с использованием нескольких контекстов?

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

@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (location = {
        "classpath:/META-INF/spring/applicationContext.xml",
        "classpath:/META-INF/spring/applicationContext-security.xml"})
@Configurable
public class UserDetailsServiceImplIntegrationTest {

    @Autowired
    UserDataOnDemand dod;
    // @Autowired не работает для этого компонента из applicationContext-security.xml
    UserDetailsService userDetailsService;

    @ Перед общедоступной установкой void () {
        dod.init();
        // Обходной путь для проблемы с автопроводкой userDetailsService = (UserDetailsService)ctx.getBean("userDetailsService");
    }

    @Test
    public void testLoadUser() {
        UserDetails ud = userDetailsService.loadUserByUsername("david@somewhere.co.za");
        Assert.assertEquals("david@somewhere.co.za", ud.getUsername());
    }
}

Я использую Spring 3.0.3.

Вот трассировка стека, когда я раскомментирую строку @Autowired для UserDetailsService:

org.springframework.beans.factory.BeanCreationException: Ошибка при создании bean-компонента с именем 'za.co.acme.app.security.UserDetailsServiceImplIntegrationTest': не удалось выполнить внедрение зависимостей с автоматической связью; Вложенное исключение: org.springframework.beans.factory.BeanCreationException: Не удалось автоматически связать поле: org.springframework.security.core.userdetails.UserDetailsService za.co.acme.app.security.UserDetailsServiceImplInsergrationSertailSertailServiceS. вложенное исключение - org.springframework.beans.factory.NoSuchBeanDefinitionException: не найден соответствующий компонент типа [org.springframework.security.core.userdetails.UserDetailsService] для зависимости: ожидается, что по крайней мере 1 компонент, который квалифицируется как кандидат для автосопровождения для этой зависимости. Аннотации зависимостей: {@org.springframework.beans.factory.annotation.Autowired(обязательный =true)} в org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues ​​(AutowiredAnost.Prog.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1064) при org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireBeanProperties(AbstractAutowireCapableBeanFactory.java:374) при org.springframework.beans.factory.wiring.BeanConfigurerSupport.configureBean(BeanConfigurerSupport.java:140) при org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect.configureBean(AnnotationBeanConfigurerAspect.aj:59) в org.springframework.beans.factory.aspectj.AbstractDependencyInjectionAspect.ajc$afterReturning$org_springframework_beans_factory_aspectj_AbstractDependencyInjectionAspect$2$1ea6722c(AbstractDependencyInjectionAspect, 39) в sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27) в java.lang.reflect.Constructor.newInstance(Constructor.java:513) в org.junit.restners.BlockJUnitj.jer4Run.Class)

Бин определенно существует, так как поиск по имени работает, и он имеет правильный тип.

6 ответов

Обходной путь - создать новый единственный файл конфигурации (назовем его "test-configuration.xml"), который включает в себя и applicationContext.xml, и applicationContext-security.xml. Затем вы можете использовать эти конфигурации в своих тестах.

тест-configuration.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

    <import resource="classpath:/META-INF/spring/applicationContext.xml"/>
    <import resource="classpath:/META-INF/spring/applicationContext-security.xml"/>
</beans>

UserDetailsServiceImplIntegrationTest.java:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/test-configuration.xml")
@Configurable
public class UserDetailsServiceImplIntegrationTest {
...
}

У меня была та же проблема, решение исправило мою проблему - переключение бобов через интерфейс. (т.е.) ваш ссылочный тип компонента должен быть интерфейсом, а не классом реализации

В вашем случае поменяйте конкретный класс UserDetailsService ссылка с его интерфейсом.

Например:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {
        "classpath:/META-INF/spring/applicationContext.xml",
        "classpath:/META-INF/spring/applicationContext-security.xml"})
@Configurable
public class UserDetailsServiceImplIntegrationTest {

  //modified code  
  @Autowired
  IUserDetailsService userDetailsService;

    //your test cases follows

}

ПРИМЕЧАНИЕ: я знаю, что это не будет разумным решением, но попробуйте, я очень переживал из-за этой же ошибки и, наконец, изменил свою ссылку, и она работала нормально. Надеюсь, это решит вашу проблему.

У меня есть аналогичная настройка, и она отлично работает для меня.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:/applicationContext-struts.xml", "classpath:/applicationContext.xml" })
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
@Transactional
public abstract class BaseTests {

Я думаю, что проблема в настройке вашего проекта. Вы используете Eclipse? Загружает ли он файлы контекста из папки /bin или из папки /src? Вы исключили "applicationContext-security.xml" из сборки?

Вы должны сказать Spring действовать в соответствии с этими аннотациями. В соответствующий контекстный файл вы должны добавить следующее:

<context:annotation-config/>

Теперь он будет сканировать эти аннотации. См. Документацию Spring по настройке на основе аннотаций.

Чтобы ограничить количество классов, которые необходимо сканировать, чтобы не выполнять ненужное сканирование пакетов без автоматической проводки, добавьте следующее:

<context:component-scan base-package="org.example"/>

Подробнее об этом см. В документах по автоматическому определению компонентов, а также о пространствах имен XML, которые необходимо добавить для ссылки на эти теги.

У меня те же проблемы. Кажется, что вместо реальной UserDataOnDemand существует прокси UserDataOnDemand .

Как называется боб userDetailsService в вашем xml? Вам может понадобиться добавить @Qualifier аннотация с именем бина, а затем положить <qualifier> тег в контексте.

Взгляните на документацию Spring по этой теме.

Другие вопросы по тегам