Disable @EnableScheduling on Spring Tests

巧了我就是萌 提交于 2019-11-27 07:45:23

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")

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.

In each Test you define which spring configuration should be used, currently you have:

@ContextConfiguration(classes={AppConfiguration.class})

Common practice is to define separate spring configuration for your normal application and for your tests.

AppConfiguration.java 
TestConfiguration.java

Then in your test you simply refference TestConfiguration instead of your current AppConfiguration using @ContextConfiguration(classes={TestConfiguration.class})

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

This way you can configure any setting for your tests differently than in production code. You can for example use in-memory database for your tests instead of regular one and much more.

I was able to solve this problem by creating a method that removes the scheduled tasks during unit tests. Here is an example:

    import org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor;
    import org.springframework.context.ApplicationContext;

    public static void removeSchedulledTasks(ScheduledAnnotationBeanPostProcessor postProcessor, ApplicationContext appContext) {

    postProcessor.setApplicationContext(appContext);

    Iterator<ScheduledTask> iterator = postProcessor.getScheduledTasks().iterator();

    while(iterator.hasNext()) {

        ScheduledTask taskAtual = iterator.next();
        taskAtual.cancel();

    }

}

Use example:

import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import com.example.Utils;


@RunWith(SpringRunner.class)
@SpringBootTest
public class TestRemoveScheduller {


    @Autowired
    private ScheduledAnnotationBeanPostProcessor postProcessor;

    @Autowired
    private ApplicationContext appContext;


    @Before
    public void init(){

        //Some init variables

        //Remove schedulled tasks method
        Utils.removeSchedulledTasks(postProcessor, appContext);

    }

    //Some test methods

}

Hope this helps.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!