속닥속닥의 알림 기능을 비동기 이벤트 방식으로 풀어내고 테스트를 하는 과정에서 비동기에 대한 테스트를 하기 어려운 문제를 맞이했다. 따라서, 테스트 환경은 동기 방식으로 진행했는데 방법을 공유하려고 한다.
https://velog.io/@byeongju/%EC%86%8D%EB%8B%A5%EC%86%8D%EB%8B%A5-%EC%95%8C%EB%A6%BC-%EA%B8%B0%EB%8A%A5-%EA%B0%9C%EC%84%A0%EA%B8%B0-1
테스트를 동기로 가져간 이유는 아래의 글의 테스트 부분을 읽어보면 좋을 것 같다.
방법은 꽤 간단하다. 아래의 코드는 비동기 처리를 위한 ThreadPoolTaskExecutor
를 Bean으로 등록하는 Configuration이다. 정확히 말하면 ThreadPoolTaskExecutor가 비동기를 Task를 처리하는 것은 아니고, ThreadPoolExecutor
가 이를 처리하는데 ThreadPoolExecutor를 관리하고 모니터링하는 객체이다. ThreadPoolTaskExecutor는 내부적으로 ThreadPoolExecutor를 가지고 있다.
다시 본론으로 돌아와서, @SpringBootTest 를 통해 해당 Bean이 초기화되는데 이를 다른 Bean으로 바꿔치기
하는 방식을 사용하면 된다.
@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {
@Override
@Bean(name = "asyncExecutor")
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(CORE_POOL_SIZE);
executor.setMaxPoolSize(MAX_POOL_SIZE);
executor.setQueueCapacity(QUEUE_CAPACITY);
executor.setThreadNamePrefix(THREAD_NAME_PREFIX);
executor.initialize();
return executor;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return AsyncConfigurer.super.getAsyncUncaughtExceptionHandler();
}
}
출처 : https://stackoverflow.com/questions/29743320/how-exactly-does-the-spring-beanpostprocessor-work
위의 그림에서 Bean Post Processors를 보면 Bean이 초기화되기 전후로 특정 작업을 하는 것으로 보인다.
여기서 아래와 같이 빈으로 등록되는 ThreadPoolTaskExecutor를 SyncTaskExecutor로 바꾸는 것
이다.
@TestConfiguration
public class AsyncTestConfig {
@Bean
public AsyncExecutorPostProcessor asyncExecutorPostProcessor() {
return new AsyncExecutorPostProcessor();
}
static class AsyncExecutorPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (beanName.equals("asyncExecutor")) {
return new SyncTaskExecutor();
}
return bean;
}
}
}
위와 같이 BeanPostProcessor의 구현체를 빈으로 등록
하고 postProcessAfterInitialization
를 구현하면 된다.
ApplicationContext가 load 되는 과정에서, Bean들이 postProcessAfterInitialization에 매개변수로 들어온다. 들어오는 Bean 중에 비동기 처리를 위한 Thread Pool을 담당하는 빈의 이름일 경우, SyncTaskExecutor라는 동기 방식의 SyncTaskExecutor
로 바꿔주면 된다.
끗.
우아한테크코스 4기 더즈