Pregunta

estamos utilizando la primavera para mis propósitos de aplicación y marco de pruebas de la primavera de las pruebas unitarias. Tenemos un pequeño problema, sin embargo: el código de la aplicación carga un contexto de aplicación de primavera de una lista de ubicaciones (archivos XML) en la ruta de clase. Pero cuando nos encontramos nuestras pruebas de unidad, queremos que algunos de los granos de primavera, que se burla en lugar de clases de implementación de pleno derecho. Por otra parte, para algunas pruebas de unidad que queremos algunos granos para convertirse en burla, mientras que para otras pruebas de unidad que queremos otros granos para convertirse en burla, ya que estamos probando diferentes capas de la aplicación.

Todo esto significa que quiero para redefinir los granos específicos del contexto de aplicación y refrescar el contexto cuando se desee. Mientras hace esto, quiero volver a definir sólo una pequeña porción de los granos situados en uno (o varios) original de archivo de definición de los granos de XML. No puedo encontrar una manera fácil de hacerlo. Siempre ha considerado que la primavera es una unidad de pruebas marco amigable por lo que debe estar pasando algo aquí.

¿Tiene alguna idea de cómo hacerlo?

Gracias.

¿Fue útil?

Solución

Yo propondría un TestClass costumbre y algunas reglas sencillas para la ubicación de la bean.xml primavera

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {
    "classpath*:spring/*.xml",
    "classpath*:spring/persistence/*.xml",
    "classpath*:spring/mock/*.xml"})
@Transactional
@TestExecutionListeners({
    DependencyInjectionTestExecutionListener.class,
    TransactionalTestExecutionListener.class,
    DirtiesContextTestExecutionListener.class})
public abstract class AbstractHibernateTests implements ApplicationContextAware 
{

    /**
     * Logger for Subclasses.
     */
    protected final Logger LOG = LoggerFactory.getLogger(getClass());

    /**
     * The {@link ApplicationContext} that was injected into this test instance
     * via {@link #setApplicationContext(ApplicationContext)}.
     */
    protected ApplicationContext applicationContext;

    /**
     * Set the {@link ApplicationContext} to be used by this test instance,
     * provided via {@link ApplicationContextAware} semantics.
     */
    @Override
    public final void setApplicationContext(
            final ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }
}

si hay maqueta bean.xml en la ubicación especificada, se anulan todas bean.xml "real" en los lugares "normales" - sus ubicaciones normales pueden diferir

... pero yo nunca mezclar los granos de simulacros y no simulados que es difícil rastrear los problemas, cuando la aplicación crece.

Otros consejos

Una de las razones de primavera se describe como la prueba de usar es porque puede ser fácil simplemente nueva o cosas por simulacro en la prueba unitaria.

Como alternativa se ha utilizado el siguiente configuración con gran éxito, y creo que está bastante cerca de lo que usted quiere, me muy recomiendo:

Para todos los granos que necesitan diferentes implementaciones en diferentes contextos, cambiar al cableado basado anotación. Puede dejar a los demás tal y como son.

Implementar el siguiente conjunto de anotaciones

 <context:component-scan base-package="com.foobar">
     <context:include-filter type="annotation" expression="com.foobar.annotations.StubRepository"/>
     <context:include-filter type="annotation" expression="com.foobar.annotations.TestScopedComponent"/>
     <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
 </context:component-scan>

A continuación, realizar anotaciones en las Live implementaciones con @Repository, sus stub implementaciones con @StubRepository, cualquier código que debe estar presente en el dispositivo de prueba de unidad SÓLO con @TestScopedComponent . Puede ejecutar en necesidad de un par de anotaciones más, pero estos son un gran comienzo.

Si usted tiene una gran cantidad de spring.xml, es probable que tenga que hacer algunos archivos XML de Spring nuevos que, básicamente, sólo contienen las definiciones de componentes de escaneo. Se podría normalmente acaba de anexar estos archivos a su lista de @ContextConfiguration regular. La razón de esto se debe a que con frecuencia termina con diferentes configuraciones del contexto-scan (confía en mí, que al menos 1 anotaciones más si está haciendo pruebas web, lo que hace de 4 combinaciones pertinentes)

A continuación, básicamente utiliza el

@ContextConfiguration(locations = { "classpath:/path/to/root-config.xml" })
@RunWith(SpringJUnit4ClassRunner.class)

Tenga en cuenta que esta configuración hace no le permiten tener combinaciones alternas de datos ramal / en vivo. Tratamos esto, y creo que resultó en un lío que no recomendaría a nadie;) O bien posada alambre de la serie completa de los talones o el conjunto completo de servicios en tiempo real

.

Utilizamos principalmente dependencias del trozo de auto-cableado cuando se prueba GUI cerca de las cosas donde las dependencias suelen ser bastante sustancial. En las zonas más limpias del código que usamos pruebas unitarias más regular.

En nuestro sistema tenemos los siguientes archivos XML para el componente de exploración:

  • para la producción de web normal
  • para comenzar web con talones única
  • para pruebas de integración (en junit)
  • para pruebas de unidad (en junit)
  • para las pruebas web de selenio (en junit)

Esto significa que estamos en total con 5 configuraciones diferentes de todo el sistema que podemos empezar con la aplicación. Ya que sólo utilizamos las anotaciones, la primavera es lo suficientemente rápido para Autowire incluso aquellas pruebas de unidad que queremos cable. Sé que esto es poco tradicional, pero es realmente grande.

a cabo pruebas de integración se ejecutan con la configuración completa en vivo, y una vez o dos veces me han decidido a obtener realmente pragmática y quieren tener un 5 cableados en directo y una única maqueta:

public class HybridTest {
   @Autowired
   MyTestSubject myTestSubject;


   @Test
   public void testWith5LiveServicesAndOneMock(){
     MyServiceLive service = myTestSubject.getMyService();
     try {
          MyService mock = EasyMock.create(...)
          myTestSubject.setMyService( mock);

           .. do funky test  with lots of live but one mock object

     } finally {
          myTestSubject.setMyService( service);
     }


   }
}

Sé que los puristas de las pruebas van a ser todo sobre mí para esto. Pero a veces es sólo una solución muy pragmática que resulta ser muy elegante cuando la alternativa sería muy, muy feo. Una vez más es por lo general en aquellas áreas gui-cerca.

con la anotación @InjectedMock

Me salvó un montón de tiempo. Sólo tiene que utilizar

@Mock
SomeClass mockedSomeClass

@InjectMock
ClassUsingSomeClass service

@Before
public void setUp() {
    MockitoAnnotations.initMocks(this);
}

y todos sus problemas se resuelven. Mockito sustituirá a la inyección de dependencias de la primavera con una maqueta. Acabo de utilizar yo mismo y funciona muy bien.

Hay algunas soluciones muy complicadas y de gran alcance que figuran aquí.

Pero hay una FAR modo , mucho más fácil de lograr lo que ha pedido a Stas, que no implica la modificación de que no sea una línea de código en el método de prueba nada. Funciona para pruebas unitarias y pruebas de integración de Primavera por igual, para las dependencias autowired, privada y campos protegidos.

Aquí está:

junitx.util.PrivateAccessor.setField(testSubject, "fieldName", mockObject);

También puede escribir pruebas unitarias para no requerir cualquier búsqueda en absoluto:

@ContextConfiguration(locations = { "classpath:/path/to/test-config.xml" })
@RunWith(SpringJUnit4ClassRunner.class)
public class MyBeanTest {

    @Autowired
    private MyBean myBean; // the component under test

    @Test
    public void testMyBean() {
        ...
    }
}

Esto proporciona una manera fácil de mezclar y combinar archivos de configuración reales con los archivos de configuración de prueba.

Por ejemplo, cuando se utiliza de hibernación, que podría tener mi grano de sessionFactory en un archivo de configuración (para ser utilizado tanto en las pruebas y la aplicación principal), y tienen por frijol dataSource en otro archivo de configuración (se podría utilizar un DriverManagerDataSource a una db en memoria, y el otro puede utilizar un JNDI-lookup).

Pero, sin duda, mire de @ Cletus advertencia; -)

Fácil. Se utiliza un contexto de aplicación personalizada para las pruebas unitarias. O no se utiliza en absoluto y se crea manualmente y se inyecta sus granos.

Me suena como su prueba podría ser un poco demasiado amplia. Las pruebas unitarias se trata de pruebas, así, las unidades. Un grano de primavera es un buen ejemplo de una unidad. No debería ser necesario un contexto de aplicación entera para eso. Me parece que si su unidad de pruebas es tan alto nivel que se necesita cientos de frijoles, las conexiones de bases de datos, etc, entonces tienen una prueba de unidad muy frágil que se va a romper en el siguiente cambio, será difícil de mantener y realmente ISN' t añadir mucho valor.

Puede utilizar la función href="http://static.springframework.org/spring/docs/2.5.x/reference/beans.html" rel="nofollow noreferrer"> importación en

Yo no tengo los puntos de reputación a la pila en la respuesta de duffymo, pero yo sólo quería meter su cuchara y decir la suya era la respuesta "correcta" para mí.

una instancia de un FileSystemXmlApplicationContext en la configuración de la unidad de prueba con un applicationContext.xml personalizado. En ese XML personalizado, en la parte superior, hacer una duffymo como indica. A continuación, declarar sus granos de simulacros, fuentes de datos no JNDI, etc, que anulará los identificadores declarados en la importación.

funcionaba como un sueño para mí.

Tal vez usted podría utilizar calificadores para sus granos? Se podría redefinir los granos que desea maqueta en un contexto de aplicación separada y etiquetarlos con una "prueba" de clasificación. En las pruebas unitarias, al realizar el cableado sus granos especifique siempre el calificativo de "prueba" para utilizar las maquetas.

Quiero hacer lo mismo, y estamos encontrando que es esencial.

El mecanismo actual que usamos es básicamente manual, pero funciona.

Digamos por ejemplo, que desea burlarse cabo frijol de tipo Y. Lo que hacemos es cada grano que tiene esa dependencia hacemos implementar una interfaz - "IHasY". Esta interfaz es

interface IHasY {
   public void setY(Y y);
}

A continuación, en nuestra prueba que llamamos el método util ...

 public static void insertMock(Y y) {
        Map invokers = BeanFactory.getInstance().getFactory("core").getBeansOfType(IHasY.class);
        for (Iterator iterator = invokers.values().iterator(); iterator.hasNext();) {
            IHasY invoker = (IHasY) iterator.next();
            invoker.setY(y);
        }
    }

No quiero crear un archivo XML entero sólo para inyectar esta nueva dependencia y por eso me gusta esto.

Si usted está dispuesto a crear un archivo XML de configuración a continuación, el camino a seguir sería la creación de una nueva fábrica con los granos de simulacros y hacer que su fábrica por defecto uno de los padres de esta fábrica. Asegúrese entonces que cargar todos los granos de la nueva fábrica de niño. Al hacer esto, el sub-fábrica anulará los frijoles en la fábrica de los padres cuando los identificadores de frijol son los mismos.

Ahora bien, si, en mi prueba, si pudiera programación crear una fábrica, que sería impresionante. Tener que usar XML es demasiado engorroso. Estoy mirando para crear esa fábrica de niño con código. A continuación, cada prueba puede configurar su fábrica de la manera que quiera. No hay ninguna razón por la cual una fábrica como que no va a funcionar.

primavera-reinyectar está diseñado para sustituir los granos con burla.

Desde el PO esto ha llegado a lo largo: Springockito

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top