Disable @EnableScheduling on Spring Tests

后端 未结 7 849
天涯浪人
天涯浪人 2020-11-30 02:35

When I run my unit tests, it invokes my scheduled tasks. I want to prevent this behaviour, which is caused by the fact that I have @EnableScheduling on my main

相关标签:
7条回答
  • 2020-11-30 03:19

    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.

    0 讨论(0)
  • 2020-11-30 03:22

    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")
    
    0 讨论(0)
  • 2020-11-30 03:26

    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.

    0 讨论(0)
  • 2020-11-30 03:31

    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.

    0 讨论(0)
  • 2020-11-30 03:32

    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 removeScheduledTasks(ScheduledAnnotationBeanPostProcessor postProcessor, ApplicationContext appContext) {
            postProcessor.setApplicationContext(appContext);
            postProcessor.getScheduledTasks().forEach(ScheduledTask::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 scheduled tasks method
            Utils.removeScheduledTasks(postProcessor, appContext);
            
        }
    
        //Some test methods
    
    }
    

    Hope this helps.

    0 讨论(0)
  • 2020-11-30 03:36

    With Spring Boot and cron expression you can enable or disable scheduling. For example you can define an test application.yml and set

    scheduler:
      cron-expr: '-'
    

    See also disable scheduling with '-'. In your scheduler class you can pass the expression.

    @Scheduled(cron = "${scheduler.cron-expr}")
    
    0 讨论(0)
提交回复
热议问题