scheduled job examples enable create spring unit-testing junit junit4 springjunit4classrunner

job - spring scheduled cron



Deshabilitar @EnableScheduling en pruebas de primavera (4)

Acabo de parametrizar mi anotación @Scheduled con tiempos de retardo configurables:

@Scheduled(fixedRateString = "${timing.updateData}", initialDelayString = "${timing.initialDelay}")

En mi aplicación de prueba.yaml:

timing: updateData: 60000 initialDelay: 10000000000

Y principal application.yaml:

timing: updateData: 60000 initialDelay: 1

No lo está apagando, pero creando un retraso tan largo, las pruebas serán largas antes de que se ejecute. No es la solución más elegante, pero definitivamente una de las más fáciles que he encontrado.

Cuando ejecuto mis pruebas unitarias, invoca mis tareas programadas. Quiero evitar este comportamiento, que es causado por el hecho de que tengo @EnableScheduling en la configuración principal de mi aplicación.

¿Cómo puedo desactivar esto en mis pruebas unitarias?

Me he encontrado con esta question/answer que sugiere la creación de perfiles?

No estoy seguro de cómo iba a hacer eso? o si es un exceso? Estaba pensando en tener una AppConfiguration por separado para mis pruebas unitarias, pero parece que estoy repitiendo el código dos veces cuando hago eso.

@Configuration @EnableJpaRepositories(AppConfiguration.DAO_PACKAGE) @EnableTransactionManagement @EnableScheduling @ComponentScan({AppConfiguration.SERVICE_PACKAGE, AppConfiguration.DAO_PACKAGE, AppConfiguration.CLIENT_PACKAGE, AppConfiguration.SCHEDULE_PACKAGE}) public class AppConfiguration { static final String MAIN_PACKAGE = "com.etc.app-name"; static final String DAO_PACKAGE = "com.etc.app-name.dao"; private static final String ENTITIES_PACKAGE = "com.etc.app-name.entity"; static final String SERVICE_PACKAGE = "com.etc.app-name.service"; static final String CLIENT_PACKAGE = "com.etc.app-name.client"; static final String SCHEDULE_PACKAGE = "com.etc.app-name.scheduling"; @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory(){ // stripped code for question readability } // more app config code below etc }

Ejemplo de prueba unitaria

@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes={AppConfiguration.class}) @Transactional @TransactionConfiguration(defaultRollback = true) @WebAppConfiguration public class ExampleDaoTest { @Autowired ExampleDao exampleDao; @Test public void testExampleDao() { List<Example> items = exampleDao.findAll(); Assert.assertTrue(items.size()>0); } }


En cada prueba, usted define qué configuración de resorte se debe utilizar, y actualmente tiene:

@ContextConfiguration(classes={AppConfiguration.class})

La práctica común es definir una configuración de resorte separada para su aplicación normal y para sus pruebas.

AppConfiguration.java TestConfiguration.java

Luego, en su prueba, simplemente TestConfiguration lugar de su AppConfiguration actual usando @ContextConfiguration(classes={TestConfiguration.class})

@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes={TestConfiguration.class}) @Transactional @TransactionConfiguration(defaultRollback = true) @WebAppConfiguration public class ExampleDaoTest

De esta forma puede configurar cualquier configuración para sus pruebas de forma diferente que en el código de producción. Por ejemplo, puede usar la base de datos en memoria para sus pruebas en lugar de la habitual y mucho más.


Si no desea usar perfiles, puede agregar un marcador que habilitará / deshabilitará la programación para la aplicación

En su AppConfiguration agregue esto

@ConditionalOnProperty( value = "app.scheduling.enable", havingValue = "true", matchIfMissing = true ) @Configuration @EnableScheduling public static class SchedulingConfiguration { }

y en tu prueba simplemente agrega esta anotación para deshabilitar la programación

@TestPropertySource(properties = "app.scheduling.enable=false")


Una alternativa sería anular el registro del procesador de posos de frijol que programa los eventos. Esto se puede hacer simplemente colocando la siguiente clase en el classpath de sus pruebas:

public class UnregisterScheduledProcessor implements BeanFactoryPostProcessor { @Override public void postProcessBeanFactory(final ConfigurableListableBeanFactory beanFactory) throws BeansException { for (String beanName : beanFactory.getBeanNamesForType(ScheduledAnnotationBeanPostProcessor.class)) { ((DefaultListableBeanFactory)beanFactory).removeBeanDefinition(beanName); } } }

Si bien esto es bastante simple y parece hacer el trabajo, tenga en cuenta que no probé esto mucho o verifico las posibles implicaciones de eliminar un bean definido del registro o asegurarme de que el pedido de PostProcessors no sea un problema ...