Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

146
Vistas
Mejores prácticas de contexto de prueba de Spring

Estoy tratando de cubrir una gran aplicación Spring Boot con pruebas de integración. Hay muchos frijoles Spring dentro de la aplicación. Se tarda un tiempo en cargar el contexto de Spring.

Así que me pregunto -

  • ¿Es Spring lo suficientemente inteligente como para compartir el mismo contexto entre múltiples pruebas de integración ubicadas en diferentes clases? Me refiero a evitar inicializar el contexto pesado para cada clase de prueba.
  • ¿Qué sucede cuando las pruebas 1,2,4 usan TestContextOne y las pruebas 3,5 usan TestContextTwo ? ¿Spring los lanza en orden 1,2,4,3,5? ¿O Spring mantiene dos contextos en la memoria?

PD En otras palabras, ¿es la práctica común usar un único Spring Context "completo" para todas las pruebas de integración, en lugar de escribir uno separado para cada prueba?

about 4 years ago · Santiago Trujillo
2 Respuestas
Responde la pregunta

0

Una de las características principales proporcionadas por Spring Framework para probar una aplicación es el mecanismo de almacenamiento en caché de contexto para evitar exactamente lo que menciona sobre la sobrecarga de carga. La documentación de primavera dice que:

Una vez que el marco TestContext carga un ApplicationContext (o WebApplicationContext ) para una prueba, ese contexto se almacenará en caché y se reutilizará para todas las pruebas posteriores que declaren la misma configuración de contexto única dentro del mismo conjunto de pruebas.

Con esta afirmación en mente, debe comprender cómo funciona el mecanismo de caché para determinar la mejor estrategia para construir sus pruebas. La pregunta aquí es: When spring caches the context, it stores this context in memory using what key? . Según la documentación, la clave se basa en algunos parámetros del contenedor:

Un ApplicationContext se puede identificar de forma única mediante la combinación de parámetros de configuración que se utilizan para cargarlo. En consecuencia, la combinación única de parámetros de configuración se utiliza para generar una key bajo la cual se almacena en caché el contexto. El marco TestContext utiliza los siguientes parámetros de configuración para construir la clave de caché de contexto:

locations (de @ContextConfiguration)
classes (de @ContextConfiguration)
contextInitializerClasses (de @ContextConfiguration)
contextCustomizers (de ContextCustomizerFactory)
contextLoader (de @ContextConfiguration)
parent (de @ContextHierarchy)
perfiles activos (de activeProfiles )
propertySourceLocations (de @TestPropertySource)
propertySourceProperties (de @TestPropertySource)
resourceBasePath (de @WebAppConfiguration)

Con base en esta información, puedo sugerirle que la mejor práctica es organizar sus pruebas de manera que usen el mismo conjunto de parámetros de contexto (es decir, la misma clave de caché) para beneficiarse del mecanismo de caché y evitar que se cargue otro contexto. La documentación de Spring también da un ejemplo:

..., si TestClassA especifica {"app-config.xml", "test-config.xml"} para el atributo de ubicación (o valor) de @ContextConfiguration, el marco TestContext cargará el ApplicationContext correspondiente y lo almacenará en un archivo estático caché de contexto bajo una clave que se basa únicamente en esas ubicaciones. Entonces, si TestClassB también define {"app-config.xml", "test-config.xml"} para sus ubicaciones (ya sea explícita o implícitamente a través de la herencia) pero no define @WebAppConfiguration , un ContextLoader diferente, diferentes perfiles activos, diferente contexto inicializadores, fuentes de propiedades de prueba diferentes o un contexto principal diferente, ambas clases de prueba compartirán el mismo ApplicationContext . Esto significa que el costo de configuración para cargar un contexto de aplicación se incurre solo una vez (por conjunto de pruebas), y la ejecución de la prueba posterior es mucho más rápida.

about 4 years ago · Santiago Trujillo Denunciar

0

Otro truco que puede usar en sus pruebas de integración es forzar que todos los beans en el contexto sean "perezosos". Esto es realmente útil cuando se ejecuta solo una prueba de integración, ya que no tiene que esperar a que se cargue e inicialice todo el contexto de la aplicación. Esto puede mejorar significativamente el tiempo que lleva ejecutar una sola prueba.

Puede encontrarse con situaciones en las que los beans se crean implícitamente (Ejemplo: Spring IntegrationFlow). El flujo nunca se inyecta directamente en nada, pero sus clases pueden tener referencias a beans que crea el flujo. En este caso, debe @Autowire su flujo (para asegurarse de que se creen los beans implícitos) o puede ser creativo con un BeanPostProcessor.

Creé el siguiente posprocesador y solo tiene que agregarlo a su contexto de primavera de prueba.

 public class LazyInitBeanFactoryPostProcessor implements BeanFactoryPostProcessor { private Class<?>[] exclusionList; public LazyInitBeanFactoryPostProcessor() { } public LazyInitBeanFactoryPostProcessor(Class<?>[] exclusionList) { this.exclusionList = exclusionList; } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { //Iterate over all bean, mark them as lazy if they are not in the exclusion list. for (String beanName : beanFactory.getBeanDefinitionNames()) { if (isLazy(beanName, beanFactory)) { BeanDefinition definition = beanFactory.getBeanDefinition(beanName); definition.setLazyInit(true); } } } private boolean isLazy(String beanName, ConfigurableListableBeanFactory beanFactory) { if (exclusionList == null || exclusionList.length == 0) { return true; } for (Class<?> clazz : exclusionList) { if (beanFactory.isTypeMatch(beanName,clazz)) { return false; } } return true; } }

Y para usarlo:

 @SpringBootTest(webEnvironment = WebEnvironment.NONE) public class MyTest { . . . @TestConfiguration protected static class TestConfiguration { @Bean public BeanFactoryPostProcessor lazyBeanPostProcessor() { return new LazyInitBeanFactoryPostProcessor(); } }

O lo amplía con exclusiones (en este ejemplo, cualquier bean que se pueda asignar a un flujo de Spring Integration NO se marcará como perezoso:

 @TestConfiguration protected static class TestConfiguration { @Bean public BeanFactoryPostProcessor lazyBeanPostProcessor() { return new ExtendedTestLazyBeanFactoryPostProcessor(); } static private class ExtendedTestLazyBeanFactoryPostProcessor extends LazyInitBeanFactoryPostProcessor { public ServiceTestLazyBeanFactoryPostProcessor() { super(new Class<?>[] {IntegrationFlow.class}); } }
about 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda