[SPRING] Spring Boot IntegrationTest에서 @Schedule 비활성화
SPRINGSpring Boot IntegrationTest에서 @Schedule 비활성화
Spring Boot IntegrationTest에서 스케줄 자동 시작을 비활성화하려면 어떻게합니까?
감사.
해결법
-
==============================
1.외부 컴포넌트가 자동으로 스케줄링을 가능하게 할 수 있음에 유의하십시오 (Spring Framework에서 HystrixStreamAutoConfiguration 및 MetricExportAutoConfiguration 참조). 따라서 @EnableScheduling을 지정하는 @Configuration 클래스에서 @ConditionalOnProperty 또는 @Profile을 사용하려고하면 외부 구성 요소로 인해 일정이 활성화됩니다.
외부 컴포넌트가 자동으로 스케줄링을 가능하게 할 수 있음에 유의하십시오 (Spring Framework에서 HystrixStreamAutoConfiguration 및 MetricExportAutoConfiguration 참조). 따라서 @EnableScheduling을 지정하는 @Configuration 클래스에서 @ConditionalOnProperty 또는 @Profile을 사용하려고하면 외부 구성 요소로 인해 일정이 활성화됩니다.
@EnableScheduling을 통해 예약 할 수있는 하나의 @Configuration 클래스가 있지만 각각 @ConditionalOnProperty를 사용하여 @Scheduled 작업이 포함 된 클래스를 활성화 / 비활성화하는 별도의 클래스로 예약 된 작업을 갖습니다.
동일한 클래스에 @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; } }
사용자 정의 스케줄러를 사용하여 taskScheduler Bean을 작성하고 스케줄링을 가능하게하는 구성 클래스
@Configuration @EnableScheduling public class MyApplicationSchedulingConfiguration { @Bean public TaskScheduler taskScheduler() { return new ConditionalThreadPoolTaskScheduler(); } }
위의 잠재적 인 문제는 내부 Spring 클래스에 대한 종속성을 만들었으므로 향후 변경 사항이 있으면 호환성을 수정해야한다는 것입니다.
-
==============================
2.나는 같은 문제가 있었다. 내 Scheduling Bean을 사용한 Spring의 @ConditionalOnProperty 속성을 시도했지만 스케줄링은 여전히 테스트에서 활성화되었습니다.
나는 같은 문제가 있었다. 내 Scheduling Bean을 사용한 Spring의 @ConditionalOnProperty 속성을 시도했지만 스케줄링은 여전히 테스트에서 활성화되었습니다.
내가 찾은 유일한 좋은 해결 방법은 테스트 클래스의 일정 속성을 덮어 써서 작업을 실제로 실행할 기회가 없도록하는 것입니다.
실제 작업이 my.cron = 0 0/5 * * * * 속성을 사용하여 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() { } }
따라서 작업이 활성화 되더라도 4 년에 한 번 발생하는 2 월 29 일 0 일에만 실행됩니다. 그래서 당신은 그것을 실행할 가능성이 매우 적습니다.
요구 사항에 맞게 더 멋진 cron 설정을 만들 수 있습니다.
-
==============================
3.한 가지 방법은 스프링 프로파일을 사용하는 것입니다
한 가지 방법은 스프링 프로파일을 사용하는 것입니다
시험 수업에서 :
@SpringBootTest(classes = Application.class) @ActiveProfiles("integration-test") public class SpringBootTestBase { ... }
스케줄러 클래스 또는 메소드에서 :
@Configuration @Profile("!integration-test") //to disable all from this configuration public class SchedulerConfiguration { @Scheduled(cron = "${some.cron}") @Profile("!integration-test") //to disable a specific scheduler public void scheduler1() { // do something } @Scheduled(cron = "${some.cron}") public void scheduler2() { // do something } ... }
-
==============================
4.실제 Spring Boot Application 클래스가 다음과 같은 경우 :
실제 Spring Boot Application 클래스가 다음과 같은 경우 :
@SpringBootApplication @EnableScheduling public class MyApplication { public static void main(String[] args) { SpringApplication.run(MyApplication.class, args); } }
다음과 같이 통합 테스트를 위해 @EnableScheduling없이 다른 Application 클래스를 작성해야합니다.
@SpringBootApplication public class MyTestApplication { public static void main(String[] args) { SpringApplication.run(MyTestApplication.class, args); } }
그런 다음 통합 테스트에서 MyTestApplication 클래스를 다음과 같이 사용하십시오.
RunWith(SpringJUnit4ClassRunner.class) @SpringBootTest(classes = MyTestApplication.class) public class MyIntegrationTest { ... }
내가 더 좋은 방법을 찾지 못했기 때문에 그것이 내가하는 방식입니다.
-
==============================
5.Spring Boot 2.0.3에서 알아 낸 쉬운 솔루션 :
Spring Boot 2.0.3에서 알아 낸 쉬운 솔루션 :
1) 예약 된 메소드를 별도의 Bean으로 추출
@Service public class SchedulerService { @Autowired private SomeTaskService someTaskService; @Scheduled(fixedRate = 60 * 60 * 1000) public void runSomeTaskHourly() { someTaskService.runTask(); } }
2) 테스트 클래스에서 스케줄러 Bean을 조롱하십시오.
@RunWith(SpringRunner.class) @SpringBootTest public class SomeTaskServiceIT { @Autowired private SomeTaskService someTaskService; @MockBean private SchedulerService schedulerService; }
-
==============================
6.별도의 구성 클래스를 사용하여이 문제를 해결 한 다음 테스트 컨텍스트에서이 클래스를 덮어 씁니다. 따라서 응용 프로그램에 주석을 넣는 대신 별도의 구성 클래스에만 주석을 넣었습니다. 일반적인 상황 :
별도의 구성 클래스를 사용하여이 문제를 해결 한 다음 테스트 컨텍스트에서이 클래스를 덮어 씁니다. 따라서 응용 프로그램에 주석을 넣는 대신 별도의 구성 클래스에만 주석을 넣었습니다. 일반적인 상황 :
@Configuration @EnableScheduling public class SpringConfiguration {}
테스트 컨텍스트 :
@Configuration public class SpringConfiguration {}
-
==============================
7.위의 답변을 통합하십시오.
위의 답변을 통합하십시오.
또한 항상 확인 :
다음을 읽으십시오 :
from https://stackoverflow.com/questions/40684903/disable-schedule-on-spring-boot-integrationtest by cc-by-sa and MIT license