IT

Spring Boot 통합 시 @Schedule 사용 안 함시험

itgroup 2023. 7. 7. 18:56
반응형

Spring Boot 통합 시 @Schedule 사용 안 함시험

Spring Boot Integration Test에서 예약 자동 시작을 비활성화하려면 어떻게 해야 합니까?

감사해요.

외부 구성 요소가 자동으로 스케줄링을 활성화할 수 있습니다(HystrixStream 참조).자동 구성 및 메트릭 내보내기Spring Framework에서 자동 구성).그래서 만약 당신이 시도하고 사용한다면.@ConditionalOnProperty또는@Profile에서.@Configuration를 지정하는 @EnableScheduling그러면 외부 구성 요소로 인해 예약이 활성화됩니다.

하나의 솔루션

하나 가져요@Configuration▁▁via▁▁enables스래클을 통해 스케줄링을 가능하게 하는 @EnableScheduling하지만 예약된 작업을 별도의 클래스에 두고, 각 클래스에서 사용합니다.@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 클래스에서 사용자 지정 스레드 풀 작업 스케줄러를 반환하는 @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;
  }
}

사용자 지정 스케줄러를 사용하여 taskSchedulerbean 작업을 만들고 스케줄링을 활성화하는 구성 클래스

@Configuration
@EnableScheduling
public class MyApplicationSchedulingConfiguration {

  @Bean
  public TaskScheduler taskScheduler() {
    return new ConditionalThreadPoolTaskScheduler();
  }
}

위의 잠재적인 문제는 내부 Spring 클래스에 종속성을 생성했기 때문에 향후 변경 사항이 있을 경우 호환성을 수정해야 한다는 것입니다.

저도 같은 문제가 있었습니다.맛을 시험해 보았습니다.@ConditionalOnProperty내 Scheduling Bean의 속성이지만 테스트에서 여전히 Scheduling이 활성화되었습니다.

내가 찾은 유일한 좋은 해결 방법은 테스트 클래스의 예약 속성을 덮어써서 작업을 실행할 수 있는 실제 기회가 없도록 하는 것이었습니다.

속성을 사용하여 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() {
    }

}

따라서 작업이 활성화되더라도 4년에 한 번 발생하는 2월 29일 0시에만 실행됩니다.따라서 실행할 가능성은 매우 희박합니다.

당신의 요구 사항에 맞게 더 화려한 cron 설정을 생각해 낼 수 있습니다.

Spring Boot 2.0.3에서 알아낸 쉬운 해결책:

예약된 메서드를 별도의 빈에 추출

@Service
public class SchedulerService {

  @Autowired
  private SomeTaskService someTaskService;

  @Scheduled(fixedRate = 60 * 60 * 1000)
  public void runSomeTaskHourly() {
    someTaskService.runTask();
  }
}

당신의 시험 수업에서 스케줄러 빈을 조롱합니다.

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

  @Autowired
  private SomeTaskService someTaskService;

  @MockBean
  private SchedulerService schedulerService;
}

한 가지 방법은 스프링 프로필을 사용하는 것입니다.

테스트 클래스:

@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
    }

    ...
}

실제 Spring Boot Application 클래스가 다음과 같은 경우:

@SpringBootApplication   
@EnableScheduling
public class MyApplication {

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

}

다음과 같은 통합 테스트를 위해 @EnableScheduling 없이 다른 응용 프로그램 클래스를 만들어야 합니다.

@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 {

...
}

저는 더 좋은 방법을 찾지 못했기 때문에 그렇게 하고 있습니다.

별도의 구성 클래스를 사용하여 이 문제를 해결한 다음 테스트 컨텍스트에서 이 클래스를 덮어씁니다.따라서 애플리케이션에 주석을 다는 대신 별도의 구성 클래스에만 주석을 달았습니다.
일반 컨텍스트:

@Configuration
@EnableScheduling 
public class SpringConfiguration {}

테스트 컨텍스트:

@Configuration
public class SpringConfiguration {}

위의 몇 가지 답변 통합:

  • 테스트를 위해 별도의 구성 클래스를 만듭니다("TestConfiguration.class"라고도 함).
  • 다른 콩(스케줄러 등)에 대한 Mockito 주석을 활성화합니다. - Read this: 2)

    @ConditionalOnClass
    @ConditionalOnMissingBean
    @ConditionalOnBean
    @ConditionalOnJava
    @ConditionalOnJndi
    @ConditionalOnMissingClass
    @ConditionalOnExpression
    @ConditionalOnNotWebApplication
    @ConditionalOnWebApplication
    @ConditionalOnProperty
    @ConditionalOnResource
    @ConditionalOnSingleCandidate
    

또한 항상 확인:

  • 외부 장치/서비스에 따라 "application.yml" 자체 생성 속성
  • 메인 클래스 브레이킹빈 초기화 시퀀스에 대한 자동 구성 주석
  • "applicationContext.xml", "beans.xml" 또는 클래스 경로 로더

다음을 읽어 보십시오.

  • SpringBoot 자동 구성
  • Spring Boot 자동 구성 작동 방식
  • 다음과 같은 테스트를 위해 필요하지 않은 콩에 조롱 주석을 사용해 보십시오.

    @MockBean
    private StoresRatingAvgScheduler scheduler;
    
    @Before
    public void init() {
        MockitoAnnotations.initMocks(this);
    }
    

언급URL : https://stackoverflow.com/questions/40684903/disable-schedule-on-spring-boot-integrationtest

반응형