在春季引导集成测试中禁用@Schedule
如何在Spring Boot IntegrationTest上禁用计划自动启动?
谢谢。
如何在Spring Boot IntegrationTest上禁用计划自动启动?
谢谢。
请注意,外部组件可能会自动启用调度(请参阅来自 Spring Framework 的 HystrixStreamAutoConfiguration 和 MetricExportAutoConfiguration)。因此,如果您尝试在指定 的类上使用 或,则由于外部组件,调度仍将启用。@ConditionalOnProperty
@Profile
@Configuration
@EnableScheduling
有一个类支持通过 进行调度,但随后将计划的作业放在单独的类中,每个类都用于启用/禁用包含@Scheduled任务的类。@Configuration
@EnableScheduling
@ConditionalOnProperty
不要在同一类中拥有 和,否则您将遇到外部组件无论如何都要启用它的问题,因此将被忽略。@Scheduled
@EnableScheduling
@ConditionalOnProperty
例如:
@Configuration
@EnableScheduling
public class MyApplicationSchedulingConfiguration {
}
然后在单独的类中
@Named
@ConditionalOnProperty(value = "scheduling.enabled", havingValue = "true", matchIfMissing = false)
public class MyApplicationScheduledTasks {
@Scheduled(fixedRate = 60 * 60 * 1000)
public void runSomeTaskHourly() {
doStuff();
}
}
此解决方案的问题在于,每个计划的作业都需要位于其自己的类中,并指定。如果错过了该注释,则作业将运行。@ConditionalOnProperty
扩展 和 重写这些方法。在这些方法中,您可以执行检查以查看作业是否应运行。ThreadPoolTaskScheduler
TaskScheduler
然后,在使用@EnableScheduling的 @Configuration 类中,还可以创建一个名为 taskScheduler 的@Bean,它返回自定义线程池任务计划程序)。
例如:
public class ConditionalThreadPoolTaskScheduler extends ThreadPoolTaskScheduler {
@Inject
private Environment environment;
// Override the TaskScheduler methods
@Override
public ScheduledFuture<?> schedule(Runnable task, Trigger trigger) {
if (!canRun()) {
return null;
}
return super.schedule(task, trigger);
}
@Override
public ScheduledFuture<?> schedule(Runnable task, Date startTime) {
if (!canRun()) {
return null;
}
return super.schedule(task, startTime);
}
@Override
public ScheduledFuture<?> scheduleAtFixedRate(Runnable task, Date startTime, long period) {
if (!canRun()) {
return null;
}
return super.scheduleAtFixedRate(task, startTime, period);
}
@Override
public ScheduledFuture<?> scheduleAtFixedRate(Runnable task, long period) {
if (!canRun()) {
return null;
}
return super.scheduleAtFixedRate(task, period);
}
@Override
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable task, Date startTime, long delay) {
if (!canRun()) {
return null;
}
return super.scheduleWithFixedDelay(task, startTime, delay);
}
@Override
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable task, long delay) {
if (!canRun()) {
return null;
}
return super.scheduleWithFixedDelay(task, delay);
}
private boolean canRun() {
if (environment == null) {
return false;
}
if (!Boolean.valueOf(environment.getProperty("scheduling.enabled"))) {
return false;
}
return true;
}
}
使用我们的自定义调度程序创建任务调度程序 Bean 并启用调度的配置类
@Configuration
@EnableScheduling
public class MyApplicationSchedulingConfiguration {
@Bean
public TaskScheduler taskScheduler() {
return new ConditionalThreadPoolTaskScheduler();
}
}
上述内容的潜在问题是,您已经创建了对内部Spring类的依赖项,因此,如果将来有更改,则必须修复兼容性。
我遇到了同样的问题。尝试了Spring的属性与我的调度Bean,但调度仍然在测试中被激活。@ConditionalOnProperty
我发现的唯一好的解决方法是覆盖 Test 类中的调度属性,以便作业没有真正的运行机会。
如果实际作业使用属性每 5 分钟运行一次my.cron=0 0/5 * * * *
public class MyJob {
@Scheduled(cron = "${my.cron}")
public void execute() {
// do something
}
}
然后在测试类中,您可以将其配置为:
@RunWith(SpringRunner.class)
@SpringBootTest(properties = {"my.cron=0 0 0 29 2 ?"}) // Configured as 29 Feb ;-)
public class MyApplicationTests {
@Test
public void contextLoads() {
}
}
因此,即使您的作业被激活,它也只会在2月29日的第0个小时运行,每4年发生一次。所以你有一个非常渺茫的机会来运行它。
您可以提出更多花哨的cron设置来满足您的要求。