2011-06-14 14 views
14

Tengo un problema que me parece realmente extraño. Tengo la siguiente configuración:Autocableado de granos generados por el método de fábrica EasyMock?

una interfaz:

package com.example; 

public interface SomeDependency { 
} 

Un componente de resorte:

package com.example; 

@Component 
public class SomeClass { 
} 

A config pruebas de la primavera con un grano burlado generada por EasyMock:

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

    <bean id="someInterfaceMock" class="org.easymock.EasyMock" factory-method="createMock"> 
     <constructor-arg value="com.example.SomeDependency" /> 
    </bean> 
</beans> 

Y una prueba unitaria:

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration("/testconfig.xml") 
public class SomeClassTest { 

    @Autowired 
    SomeClass someClass; 

    @Autowired 
    SomeDependency someDependency; 

    @Test 
    public void testSomeClass() throws Exception { 
     assertNotNull(someClass); 
    } 

    @Test 
    public void testSomeDependency() throws Exception { 
     assertNotNull(someDependency); 
    } 
} 

El proyecto compila y las pruebas pasan sin ningún problema, es decir autowiring de ambos SomeClass (un objeto "real") y SomeDependency (un objeto mock generada por EasyMock) tener éxito.

Sin embargo, si cambio de la puesta en práctica de SomeClass a:

@Component 
public class SomeClass { 

    @Autowired 
    SomeDependency someDependency; 
} 

ambas pruebas fallan porque

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.example.SomeDependency] 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)} 

Así que mis preguntas son:

  1. ¿Por qué fracasa la primavera para autoaumentar la dependencia a SomeClass (cuando tiene éxito en autocablear la misma dependencia a SomeClassTest)?
  2. ¿Cómo puedo cambiar el SomeClassTest o testconfig.xml para hacer pasar las pruebas?

Comentario: En realidad la clase representada por SomeClass es parte de un marco. En consecuencia, no se puede actualizar fácilmente, al menos no dentro de un tiempo razonable.

Dependencias:

  • primavera: 3.0.5.RELEASE
  • EasyMock: 3,0

Editar:

A partir de la primavera 3.2 RC1, el problema con la fábrica genérica métodos y objetos simulados ha sido solved.

/Mattias

Respuesta

20

parece que el orden de las definiciones en el xml en realidad importa cuando se utiliza para crear fábricas de habas con autowiring. Si coloca la declaración de someInterfaceMock arriba de component-scan, funcionará.

Algunas aclaraciones por qué: Cuando Spring intenta autovincularse SomeClass busca un bean del tipo SomeDependency. En esta etapa, someInterfaceMock sigue siendo una fábrica, por lo que Spring verifica la firma del método de fábrica EasyMock.createMock(...), que devuelve <T>, por lo que Spring solo encuentra un Object que no es del tipo requerido.

Una mejor manera sería utilizar la interfaz FactoryBean de Spring para crear sus simulacros.

Aquí es una aplicación básica que debe trabajar: (el orden no importa)

public class EasyMockFactoryBean<T> implements FactoryBean<T> { 
    private Class<T> mockedClass; 

    public void setMockedClass(Class mockedClass) { 
     this.mockedClass = mockedClass; 
    } 

    public T getObject() throws Exception { 
     return EasyMock.createMock(mockedClass); 
    } 

    public Class<T> getObjectType() { 
     return mockedClass; 
    } 

    public boolean isSingleton() { 
     return true; 
    } 

} 

Aquí es la definición de frijol:

<bean class="com.example.EasyMockFactoryBean"> 
    <property name="mockedClass" value="com.example.Dependancy"/> 
</bean>  
+0

Gracias! La orden hizo el truco, pero creo que usaré la implementación de EasyMockFactoryBean, considerando que es probable que tenga que burlarme de otras dependencias más adelante. – matsev

Cuestiones relacionadas