복붙노트

[SPRING] Spring이 다중 컨텍스트를 사용하여 통합 테스트 클래스를 autowire하는 방법

SPRING

Spring이 다중 컨텍스트를 사용하여 통합 테스트 클래스를 autowire하는 방법

내 통합 테스트 중 하나는 여러 Spring 컨텍스트 파일을 사용합니다. Spring은 빈에서 첫 번째 컨텍스트가 아니라 두 번째 컨텍스트에서 autowires 것 같습니다. 누구든지 내가 뭘 잘못하고 있는지 또는 문제를 해결하는 방법을 알고 있습니까?

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

    @Autowired
    UserDataOnDemand dod;
    // @Autowired does not work for this bean from applicationContext-security.xml
    UserDetailsService userDetailsService;

    @Before
    public void setup() {
        dod.init();
        // workaround for autowiring problem
        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을 사용하고 있습니다.

다음은 UserDetailsService에 대해 @Autowired 행의 주석을 제거 할 때 스택 추적입니다.

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'za.co.acme.app.security.UserDetailsServiceImplIntegrationTest': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: org.springframework.security.core.userdetails.UserDetailsService za.co.acme.app.security.UserDetailsServiceImplIntegrationTest.userDetailsService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [org.springframework.security.core.userdetails.UserDetailsService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:286)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1064)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireBeanProperties(AbstractAutowireCapableBeanFactory.java:374)
    at org.springframework.beans.factory.wiring.BeanConfigurerSupport.configureBean(BeanConfigurerSupport.java:140)
    at org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect.configureBean(AnnotationBeanConfigurerAspect.aj:59)
    at org.springframework.beans.factory.aspectj.AbstractDependencyInjectionAspect.ajc$afterReturning$org_springframework_beans_factory_aspectj_AbstractDependencyInjectionAspect$2$1ea6722c(AbstractDependencyInjectionAspect.aj:89)
    at za.co.acme.app.security.UserDetailsServiceImplIntegrationTest.(UserDetailsServiceImplIntegrationTest.java:25)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    at org.junit.runners.BlockJUnit4ClassRunner.createTest(BlockJUnit4ClassRunner.java:202)

빈은 "이름으로"검색이 작동하기 때문에 분명히 존재하며 올바른 유형입니다.

해결법

  1. ==============================

    1.해결 방법은 applicationContext.xml과 applicationContext-security.xml을 모두 포함하는 새로운 단일 구성 파일 ( "test-configuration.xml"이라고 부름)을 만드는 것입니다. 그런 다음 테스트에서 이러한 구성을 사용할 수 있습니다.

    해결 방법은 applicationContext.xml과 applicationContext-security.xml을 모두 포함하는 새로운 단일 구성 파일 ( "test-configuration.xml"이라고 부름)을 만드는 것입니다. 그런 다음 테스트에서 이러한 구성을 사용할 수 있습니다.

    test-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 {
    ...
    }
    
  2. ==============================

    2.나는 비슷한 설정을 가지고 있으며 나에게 잘 작동한다.

    나는 비슷한 설정을 가지고 있으며 나에게 잘 작동한다.

    @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"을 제외 시켰습니까?

  3. ==============================

    3.나는 같은 문제를 가지고 있었고, 해결책은 인터페이스를 통해 노출 된 빈을 스위치하는 내 문제를 해결했다. (즉) 참조 빈 유형이 구현 클래스 대신 인터페이스 여야합니다.

    나는 같은 문제를 가지고 있었고, 해결책은 인터페이스를 통해 노출 된 빈을 스위치하는 내 문제를 해결했다. (즉) 참조 빈 유형이 구현 클래스 대신 인터페이스 여야합니다.

    귀하의 경우 인터페이스와 함께 구체적인 클래스 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
    
    }
    

    참고 : 나는 이것이 현명한 해결책이 될 수 없다는 것을 알고있다. 그러나 단지 시도를해라. 나는이 같은 오류로 인해 많은 것을 걱정하고 마침내 나의 레퍼런스를 바꾸었다. 그것이 당신의 문제를 해결할 수 있기를 바랍니다.

  4. ==============================

    4.그 주석에 대해 행동하도록 Spring에 지시해야합니다. 관련 컨텍스트 파일에 다음을 추가해야합니다.

    그 주석에 대해 행동하도록 Spring에 지시해야합니다. 관련 컨텍스트 파일에 다음을 추가해야합니다.

    <context:annotation-config/>
    

    이제 해당 특수 효과를 검색합니다. Annotation 기반 설정에 대한 Spring 문서를 참조하십시오.

    autowiring이없는 패키지를 불필요하게 스캔하지 않도록 검사해야하는 클래스 수를 제한하려면 다음을 추가하십시오.

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

    자세한 내용은 구성 요소 자동 검색 및 해당 태그를 참조하기 위해 추가해야 할 XML 네임 스페이스 문서를 참조하십시오.

  5. ==============================

    5.xml의 ​​userDetailsService에 대한 bean의 이름은 무엇입니까? bean 이름과 함께 @Qualifier 어노테이션을 추가 한 다음 컨텍스트에 태그를 넣어야 할 수도 있습니다.

    xml의 ​​userDetailsService에 대한 bean의 이름은 무엇입니까? bean 이름과 함께 @Qualifier 어노테이션을 추가 한 다음 컨텍스트에 태그를 넣어야 할 수도 있습니다.

    이 주제에 대한 Spring의 문서를보십시오.

  6. ==============================

    6.나는 동일한 문제가있다. 실제 UserDataOnDemand 대신에 프록시 UserDataOnDemand가있는 것으로 보인다.

    나는 동일한 문제가있다. 실제 UserDataOnDemand 대신에 프록시 UserDataOnDemand가있는 것으로 보인다.

  7. from https://stackoverflow.com/questions/3413639/how-to-get-spring-to-autowire-integration-test-class-using-multiple-contexts by cc-by-sa and MIT license