14

I'm developing a SpringBoot application using Maven.

I've a class with the @Component annotation which has a method m with the @Scheduled(initialDelay = 1000, fixedDelay = 5000) annotation. Here fixedDelay can be set to specify the interval between invocations measured from the completion of the task.

I've also the @EnableScheduling annotation in the main class as:

@SpringBootApplication
@EnableScheduling
public class FieldProjectApplication {

    public static void main(String[] args) {
        SpringApplication.run(FieldProjectApplication.class, args);
    }

}

Now whenever I run the tests, defined as :

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

...

}

the scheduled task m is also run every 5 seconds.

Of course I just want to run the scheduled task whenever the application runs. How can I do it (i.e. prevent the scheduled task to run when a test is run)?

nbro
  • 15,395
  • 32
  • 113
  • 196

1 Answers1

26

You can extract @EnableScheduling to a separate configuration class like:

@Configuration
@Profile("!test")
@EnableScheduling
class SchedulingConfiguration {
}

Once it's done, the only thing that is left is to activate "test" profile in your tests by annotating test classes with:

@ActiveProfiles("test")

Possible drawback of this solution is that you make your production code aware of tests.

Alternatively you can play with properties and instead of annotating SchedulingConfiguration with @Profile, you can make it @ConditionalOnProperty with property present only in production application.properties. For example:

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    @Configuration
    @ConditionalOnProperty(value = "scheduling.enabled", havingValue = "true", matchIfMissing = true)
    @EnableScheduling
    static class SchedulingConfiguration {

    }
}

Scheduler will not run in tests when you do one of following:

  • add property to src/test/resources/application.properties:

    scheduling.enabled=false

  • customize @SpringBootTest:

    @SpringBootTest(properties = "scheduling.enabled=false")

Maciej Walkowiak
  • 12,372
  • 59
  • 63
  • Did you understand that I don't want scheduling in my tests? Does `@Profile("!test")` mean _not_ in the tests? – nbro Oct 24 '16 at 21:24
  • It means that configuration class will be created if "test" profile is not active. – Maciej Walkowiak Oct 24 '16 at 21:25
  • What do you think about [this solution](http://stackoverflow.com/questions/29014496/disable-enablescheduling-on-spring-tests)? I've never created specific configurations (apart from annotating the main class with `@SpringBootApplication`). Where should I put new configurations, in general? – nbro Oct 24 '16 at 21:29
  • New configuration classes can be placed in the root package of your project or any subpackage - that depends on what is configured and what is the package structure. In case of scheduling - which is usually used globally for whole application I would put it to root package or even better as a static inner class of `FieldProjectApplication`. – Maciej Walkowiak Oct 24 '16 at 21:37
  • Regarding solution from another answer, you can have separate configuration classes for production and test code, but if possible I would avoid it and aim to keep test and production config as close as possible. That again heavily depends on the size and structure of your application. – Maciej Walkowiak Oct 24 '16 at 21:38
  • Could you please give a code example of your second approach with `@ConditionalOnProperty`? By the way, this `SchedulingConfiguration` class could then be placed as an inner class of the main class, i.e. the class with the `@SpringBootApplication`? – nbro Oct 24 '16 at 22:10
  • Answer updated. – Maciej Walkowiak Oct 24 '16 at 22:20
  • 1
    Thanks for trying to help! On the other hand, it doesn't seem work. I've tried either by having `@SpringBootTest(properties = "scheduling.enabled=false")` or setting `scheduling.enabled=false` in `src/test/resources/application.properties`, and a scheduled method with the following signature `@Scheduled(initialDelay = 1000, fixedDelay = 50000000)` still seems to be executed. I don't know what could be causing it to run, also because it runs just during 1 test class, which makes all this even more strange, because, as far as I've understood, the scheduled should run by default on all tests... – nbro Oct 24 '16 at 23:06
  • Perhaps it would be easier if you could reproduce it in sample project on github. – Maciej Walkowiak Oct 24 '16 at 23:59
  • I would definitely, but I can't, since I'm working on a project which not mine.. – nbro Oct 25 '16 at 00:03
  • The way I described it in the answer definitely works - meaning you can enable/disable particular configuration classes using profiles or properties - so problem has to be specific to your project. Maybe `@EnableScheduling` is used also somewhere else in your project? – Maciej Walkowiak Oct 25 '16 at 23:01
  • I have the same issue and the propsed solution does not work for me. I even removed `@EnableScheduling` completely but the scheduling was still triggered. It seems some dependecy automatically add `@EnableScheduling`. It is discussed here https://stackoverflow.com/questions/43204377/spring-boot-scheduler-runs-without-enablescheduling-annotation – Mikhail Geyer Nov 10 '22 at 10:05