[Java Spring] 비동기 메서드에 대한 테스트코드 작성법Software Development/Trial-and-error2024. 2. 1. 20:35
Table of Contents
@SpringBootTest
@ActiveProfiles("api-test")
public class ActionServiceTest {
@Autowired
private ActionApiRepository actionApiRepository;
@Autowired
private ActionService actionService;
// ThreadPoolTaskExecutor 빈을 생성하여, 비동기로 실행되는 메소드가 실행되기 전에 테스트가 종료되는 것을 방지한다.
@Autowired
private ThreadPoolTaskExecutor threadPoolTaskExecutor;
@Test
public void testWhenFollowAction() throws InterruptedException {
// GIVEN
UserFollowEvent event = UserFollowEvent.of(1L, 2L, true);
// WHEN
actionService.whenFollowAction(event);
// 이 부분에서, whenFollowAction 메소드가 비동기로 실행되기 때문에, 해당 메소드가 실행되기 전에 테스트가 종료되는 것을 방지하기 위해
ThreadPoolTaskExecutor executor = threadPoolTaskExecutor;
executor.getThreadPoolExecutor().awaitTermination(1, TimeUnit.SECONDS);
// THEN
Action savedAction = actionApiRepository.findTopByUserIdAndDomainIdAndDomainTypeAndType(
event.getUserId(), event.getTargetUserId(), DomainType.USER, NotificationType.USER_FOLLOW
).orElse(null);
assertNotNull(savedAction);
}
}
알림에 관련된 여러 서비스 레이어의 테스트 코드를 작성하는 일을 맡게 되었다.
어쩌다 보니 이 경우는 Unit 테스트가 아닌 통합 테스트의 느낌인데,
아무튼, 실제 저장된 코드까지 테스트를 하다보니 Mocking을 쓸 수는 없었다.
그래서 H2 Database에 연동을 하고(다행히 "api-test" profile은 H2에 설정되어 있었다)
저장 테스트를 하는데, 시나리오를 짜서 넣어봐도 null exception이 계속하여 발생되었다.
이유를 곰곰히 생각해보니, 원래 Service 메서드 자체가 비동기로 돌아가는 부분이었기 때문이다.
그러니까, 실제 DB에 저장되기 전에 검증을 해버리기 때문에, 계속해서 null이 발생하는 것이었다.
이를 해결하기 위해서, 자료를 찾아보던 중
https://unluckyjung.github.io/testcode/kotlin/2022/12/11/Spring-Asyc-Logic-Test/
해당 글을 참고하여 문제를 해결하게 되었다.
비동기 로직을 동기 로직으로 바꿔주는 부분에선 문제를 겪으셨다 하여,
테스트 코드에서 해당 쓰레드를 대기해주는 방식으로 문제를 해결하였다.
오늘도 고통받았지만, 비동기에 대해 좀 더 알고 성공적인 테스트코드를 만들어서 기쁠 따름이다.
9시 다 되어 퇴근!!
'Software Development > Trial-and-error' 카테고리의 다른 글
@찐빵1 :: 위기주도학습
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!