studybook
  • Introduction
  • 실무 하며 깨닫는 부분 정리
    • 옵션에 대해서
    • 코드 작성의 순서
    • 자바 프로그램에 문제가 생겼다면
    • 장애 대처법
  • Logstash, Beats 정리
  • Zookeeper 정리
  • Message Queue 정리
    • RabbitMQ 삽질
  • Java 관련 정리
    • Java Primitive Wrapper class
    • Java NIO
    • Java8 Double colon operator
    • Effective Java
      • 4장
      • 5장
      • 6장 - Enum, Annotation
      • 7장 - Method
      • 8장 - 프로그래밍 일반
      • 9장 - Exception
    • Java8 Lambda expression
    • JDBC
    • Linux에서 WatchService 이상동작
  • Spring 관련 정리
    • Spring Bean init, destroy 순서
    • Spring Async Controller
    • Spring Executable jar 웹 개발 및 배포
    • Spring Boot Font 배포 에러
    • Spring AOP
      • Spring AOP로 모든 Request 로그 남기기
    • Spring Cache
    • Spring Cloud
      • Consul로 spring 설정 관리하기
    • Spring Test
      • Spring Test DirtiesContext
      • Spring Test MockBean, SpyBean
      • Spring Test Dynamic @Scheduled
    • Spring JDBC
    • Spring Validation
    • Spring Transaction Management
      • Spring with JTA 삽질
    • Spring에서 효율적으로 Static resource 관리하기
    • Zuul을 사용해서 Spring Reverse proxy 만들기
    • Spring Security
    • 스프링 어노테이션이 안 먹힐 때 의심해볼만한 것
    • Spring Data
    • Spring Webflux
      • Tobi 강연
  • 코드 리팩토링
    • 한번에 하나씩
  • 지속적 통합 (CI)
    • Jenkins pipeline 삽질기
  • Log Aggregator 정리
    • Flume 테스트
    • Fluentd 테스트
  • Web Socket 정리
  • Akka
    • Actor 모델
    • Supervision
  • IE 8 대응 정리
  • 함수형 프로그래밍
    • 모나드
  • Netty
    • Netty 기본 예제
    • Netty 주요 특징
    • Netty 부트스트랩
    • Netty 채널 파이프라인, 코덱
    • Netty 이벤트 모델
    • Netty 바이트 버퍼
  • 스칼라 관련 정리
    • Maven으로 컴파일하기
    • Scala def 괄호 여부의 차이
    • 스칼라 function, method 차이점
    • ScalaTest와 Spring 연동하기
    • Programming in Scala
  • J2S 컨퍼런스
  • Android
    • 테스트
    • NDK
  • DDOS
  • HTTP
  • HttpClient
  • Container
    • Image 개요
    • cri-o
    • kata containers
    • Open Container Initiative Image
    • Buildkit
  • Github pages
  • Static Website
  • Webhook
  • Service Discovery Tools
    • Etcd
    • Eureka
    • Consul
      • ACL
    • 비교
  • React
    • JSX
    • React Element
    • Components, Props
    • State, Lifecycle
    • Handling Event
    • Flux
  • Vagrant
    • SSH 접속
  • Linux
    • Systemd
    • Alternatives
  • Messaging protocols
    • XMPP
    • AMQP
  • Windows
    • Windows10 내장 우분투에 ssh 클라이언트로 접속하기
    • Windows10 Hyper-V와 Virtual Box가 충돌을 일으켰을 때
    • Hyper-V 기반 docker에서 Shared Drives 설정 실패할 때
    • 윈도우 개발환경 설정
    • Docker desktop 없이 docker 환경 세팅하기
    • UWP 앱을 항상 관리자권한으로 실행하는 바로가기 만들기
  • Spring camp 2017
    • Project Reactive
    • 이벤트 소싱
    • CQRS
  • Spring webflux
  • 리액티브 프로그래밍
  • Linux Settings
    • 홈서버 백업 및 복구기
    • 홈서버 트러블슈팅
  • Kubernetes
    • k3s 설치 및 삽질
    • pod resources
    • Argo workflow
    • 트러블 슈팅
      • Kubernetes namespace의 phase가 Terminating에서 멈춰있을 때
    • 쿠버네티스 마스터
    • Knative
    • Knative Pipeline
    • Aggrerated API server
    • Accessing the API
      • Authenticating
  • Sonarqube
  • HTTP/2
  • Go
    • Go Module
    • Go dependency injection
    • Go Error handling
    • Go in Action
      • 3장 패키지
      • 4장 배열, 슬라이스, 맵
      • 5장 GO의 타입 시스템
      • 6장 동시성
      • 7장 동시성 패턴
      • 8장 표준 라이브러리
      • 9장 테스트와 벤치마킹
    • Go Channel 사용법
  • Cloud Native
Powered by GitBook
On this page
  1. Spring 관련 정리
  2. Spring Test

Spring Test Dynamic @Scheduled

캐시를 사용하는 클래스에서 테스트를 작성하던 중이었다. 해당 클래스에는 캐시 invalidation을 하는 메소드가 있었고, 이 메소드가 주기적으로 실행되어야 하기 때문에 거기에 @Scheduled를 붙여 스프링 스케쥴링을 사용하고 있었다. 그런데 이 @Scheduled 의 delay로 3분을 줬었는데, 이렇게 되니까 테스트 하나하나에 걸리는 시간이 너무 길어져서 답답하기 그지 없었다. 그래서 런타임에서 @Scheduled의 delay를 동적으로 수정하려고 구글링도 해보고, 여러가지 시도도 해봤다.

처음엔 annotation의 값을 바꿔주면 되지 않을까 싶어 열심히 자바 리플렉션 써가며 바꾸어봤는데, 생각해보니까 어차피 스케쥴링은 처음에 application context 초기화 과정에서 결정되기 때문에 annotation 값이랑은 상관없더라. 그래서 이 방법은 버리고.

두번 째로 SchedulingConfigurer를 사용해서 수정하는 방법을 시도해봤다. stack overflow를 뒤져보니까 ScheduledTaskRegistrar.addTriggerTask() 메소드를 사용해서 하라는데, 이렇게 하면 물론 런타임에 동적으로 바꿀 수는 있겠지만 테스트 하나 짜겠다고 원본 코드도 수정해야되는데다가 심지어 그 코드가 복잡해지기까지 한다. 도저히 마음에 안 드는 방법이었다. 다른 방법이 있나 생각을 좀 하다가, 혹시 이렇게 하면 되지 않을까 싶어 해보니 생각대로 동작하더라.

사용법

@RunWith(SpringRunner.class)
@SpringBootTest
public class NpushManagerDAOTest {
  @Test
  public void myTest() {
    // run test logic
  }

  @TestConfiguration
  static class SchedulingTestConfig implements SchedulingConfigurer {
    @Autowired
    private MyService service;

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
      List<IntervalTask> taskList = taskRegistrar.getFixedDelayTaskList();
      List<IntervalTask> newTaskList = new ArrayList<>();

      for (IntervalTask task : taskList) {
        ScheduledMethodRunnable runnable = (ScheduledMethodRunnable) task.getRunnable();
        if (runnable.getTarget() instanceof MyService) {
           newTaskList.add(new IntervalTask(runnable, CUSTOM_DELAY, CUSTOM_DELAY));
        }
      }

      taskRegistrar.setFixedDelayTasksList(newTaskList);
    }
  }
}

보다시피 현재 Task List를 읽어와서 내가 필요한 것들만 골라 CUSTOM_DELAY로 새로 객체를 생성하여 리스트로 만들고, 그걸 다시 끼워넣으면 끝이다.

나는 여기서 클래스만 필터링했지만 필요하다면 Method로도 구분하는게 더 안전할지도 모르겠다.

PreviousSpring Test MockBean, SpyBeanNextSpring JDBC

Last updated 7 years ago