2010-08-05 15 views
13

Una de mis pruebas de integración usa varios archivos de contexto Spring. Parece que Spring solo se conecta automáticamente a los beans desde el primer contexto y no desde el segundo. ¿Alguien sabe lo que estoy haciendo mal o cómo solucionar el problema?¿Cómo lograr que Spring autoautie la clase de prueba de integración usando contextos múltiples?

 
@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("[email protected]"); 
     Assert.assertEquals("[email protected]", ud.getUsername()); 
    } 
} 

Estoy usando Spring 3.0.3.

Aquí es el seguimiento de la pila cuando elimine la línea @Autowired para UserDetailsService:

 
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) 

El frijol es definitivamente allí desde los "por su nombre" obras de consulta, y es del tipo correcto.

+0

¿Hay algo en los registros? – Bozho

+0

Agregué un seguimiento de pila –

Respuesta

0

¿Cuál es el nombre del bean para userDetailsService en su xml? Es posible que necesite agregar una anotación @Qualifier con el nombre del bean y luego colocar una etiqueta <qualifier> en el contexto.

Eche un vistazo a Spring's documentation sobre el tema.

+0

Lo intenté y también intenté usar @Resource sin suerte. Solo tengo un bean UserDetailsService, así que por tipo también debería funcionar. Los mensajes de error indican que no se pudo encontrar ningún bean con el tipo correcto. –

7

Una solución consiste en crear un nuevo archivo de configuración único (llamémoslo "test-configuration.xml") que incluye tanto applicationContext.xml como applicationContext-security.xml. Entonces puede usar estas configuraciones dentro de sus pruebas.

prueba 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 { 
... 
} 
3

que tienen una configuración similar y está funcionando muy bien para mí.

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

Supongo que el problema está en la configuración de su proyecto. ¿Usas Eclipse? ¿Carga los archivos de contexto de la carpeta/bin o de la carpeta/src? ¿Excluyó "applicationContext-security.xml" de la compilación?

+0

Bueno, el hecho de que la búsqueda manual del bean UserDetailsService funcione indica que los archivos de contexto se están cargando de hecho. Es solo la parte de autoenvío que no funciona por alguna razón. –

+0

Gracias, esto funcionó bien para mí. – Mythul

1

Necesita decirle a Spring que actúe sobre esas anotaciones. En el archivo de contexto relevante debe agregar lo siguiente:

<context:annotation-config/> 

Ahora escaneará esas anotaciones. Consulte la documentación del resorte en Annotation-based configuration

Para limitar el número de clases que necesita para escanear por lo que no escanear innecesariamente paquetes sin autowiring, añadir lo siguiente:

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

Consulte la documentación de Auto-detecting components para más información sobre eso, así como los espacios de nombres XML que necesitarás agregar para referenciar esas etiquetas.

0

Tengo los mismos problemas. Parece que hay un proxy UserDataOnDemand en lugar del UserDataOnDemand real.

4

Tuve el mismo problema, la solución solucionó mi problema es cambiar la exposición del frijol a través de la interfaz. (yo.e) Su referencia grano de tipo debe ser una interfaz en lugar de su clase de implementación

En su caso cambiar el hormigón de referencia Clase UserDetailsService con su interfaz.

Por ejemplo:

@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 

} 

NOTA: Sé que esto no será una solución razonable, pero sólo le dan una oportunidad, me preocupaba mucho a causa de este mismo error y finalmente cambió mi referencia y funcionó bien Espero que eso resuelva tu problema.

Cuestiones relacionadas