Disable @EnableScheduling on Spring Tests
An alternative would be to unregister the bean post processor that schedules the events. This can be done by simply putting the following class on the classpath of your tests:
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);
}
}
}
While this is quite simple and seems to do the job, beware that I did not test this very much or check for possible implications of removing a defined bean from the registry or making sure that ordering of PostProcessors won't be an issue...
I just parameterized my @Scheduled annotation with configurable delay times:
@Scheduled(fixedRateString = "${timing.updateData}", initialDelayString = "${timing.initialDelay}")
In my test application.yaml:
timing:
updateData: 60000
initialDelay: 10000000000
And main application.yaml:
timing:
updateData: 60000
initialDelay: 1
It's not turning it off but creating such a long delay, the tests will be long over before it runs. Not the most elegant solution but definitely one of the easiest I've found.
If you don't want to use profiles, you can add flag that will enable/disable scheduling for the application
In your AppConfiguration
add this
@ConditionalOnProperty(
value = "app.scheduling.enable", havingValue = "true", matchIfMissing = true
)
@Configuration
@EnableScheduling
public static class SchedulingConfiguration {
}
and in your test just add this annotation to disable scheduling
@TestPropertySource(properties = "app.scheduling.enable=false")
One more solution without any change in production code, using the @MockBean
.
@RunWith(SpringRunner.class)
@SpringBootTest
@MockBean(MyScheduledClass.class)
public class MyTest {
Which will eventually replace active scheduled job or create a mocked one.
From the documentation
Mocks can be registered by type or by {@link #name() bean name}. Any existing single bean of the same type defined in the context will be replaced by the mock, if no existing bean is defined a new one will be added.