고딩왕 코범석

비동기 이벤트를 테스트하는 방법 With JUnit 본문

Language & Framework/Spring

비동기 이벤트를 테스트하는 방법 With JUnit

고딩왕 코범석 2021. 4. 10. 07:28
반응형

안녕하세요! 이번시간에는 비동기 이벤트 로직을 테스트하는 방법에 대해 알아볼까 합니다.


제가 진행하고 있는 프로젝트에서 회원가입시, 인증 메일을 보내는 기능을 구현해야했습니다. 예전 스터디올레를 클론코딩하면서 비동기 방식을 스프링에서는 어떻게 구현하는지 공부해서 그렇게 어렵지 않았고, 그럼에도 불구하고 구글링해가면서 알아봤습니다... 구현 예제들을 쉽게 찾을 수 있었습니다. 하지만... 이 부분을 테스트하는 방법을 알기 쉽지 않았습니다. 다들 테스트하는 방법이 서버를 올린 다음, 해당 로직이 잘 동작하는지 하는 테스트가 전부였어요.


그러다 구글링을 해보고, docs를 참조한 결과 테스트하는 방법을 알게 되었습니다! 우선, 저의 프로젝트에서 회원가입 및 인증메일을 보내는 과정을 그림으로 표현해보겠습니다.


image


컨트롤러 및 서비스 계층에서의 회원가입 테스트는 이전에 작성한 코드가 있었기에, 상관이 없었지만 저는 Async로 동작하는 메일 전송 기능만을 테스트하고 싶었습니다.

// Service 로직 중 일부
public SignUpResponse signUp(Dto dto){
    Account account = saveAccount(dto);    // 회원저장 (여기서 이메일토큰도 생성됩니다.)
    applicationEventPublisher.publishEvent(SendEmailToken.builder()
                .token(savedAccount.getEmailCheckToken())
                .to(savedAccount.getEmail()).build());
    return response;
}

@Slf4j
@Async
@Component
@Transactional
@RequiredArgsConstructor
public class AccountEventListener {

    private final AppProperties appProperties;
    private final EmailService emailService;

    @EventListener
    public void sendSignUpAuthenticationEmail(SendEmailToken sendEmailToken) {
        // 이걸 테스트해야합니다.
        String msg = "해당 주소로 접속하시면, 회원가입이 완료됩니다.\n"
                + appProperties.getHost() + "/check-email-token?email=" + sendEmailToken.getTo()
                + "&token=" + sendEmailToken.getToken();

        EmailMessage message = EmailMessage.builder()
                .subject("[DevIdea] 회원가입 인증 메일입니다.")
                .to(sendEmailToken.getTo())
                .message(msg)
                .build();
        emailService.sendEmail(message);
    }
}

간략하게 작성했습니다.applicationEventPublisher는 ApplicationEventPublisher 타입의 변수이며, publishEvent 메서드를 실행할 경우, 이 메서드의 파라미터 타입에 해당하는 이벤트를 스프링의 @EventListener가 동작시키는 방식입니다.


이제, 테스트를 작성해볼게요. 테스트 코드는 다음과 같습니다.


@SpringBootTest
@RecordApplicationEvents
class AccountEventListenerTest {

    @Autowired
    AccountService accountService;
    @Autowired
    ApplicationEvents events;

    @Test
    void 인증메일_비동기_테스트() throws Exception {

//        given
        SignUp.CommonRequest request = AccountDummy.getSignUpRequest();

//        when
        accountService.signUp(request);

//        then
        int count = (int) events.stream(SendEmailToken.class).count();
        assertEquals(1, count);
    }
}

@RecordApplicationEvents

org.springframework.test.context.event 패키지에 속해있습니다. 단일 테스트로 실행되는 동안 애플리케이션에서 발생하는 Event들을 record 해주는 어노테이션이에요! 이 어노테이션은 클레스 레벨에서 작성 가능합니다.


ApplicationEvents

이 친구도 org.springframework.test.context.event 패키지에 속해있습니다. 이 객체를 사용하려면 클래스 레벨에 @RecordApplicationEvents가 존재해야 합니다.


테스트 작성 시, 스트림을 통해 이벤트가 발생한 클래스를 매개변수에 넣어주고, 이벤트가 몇번 발생했는지 카운트 메서드로 세어 리턴을 받습니다 (int count)


이제 실행해볼까요?


image


성공했습니다. 오늘은 간단하게 비동기 이벤트를 어떻게 테스트하는지에 대해 포스팅해보았는데, 자세한 내용은 docs를 참조하시면 좋을것 같습니다. 그럼 안녕...!

반응형

'Language & Framework > Spring' 카테고리의 다른 글

[MSA] Service Discovery  (0) 2021.05.06
Service Layer 분리하기!  (0) 2021.05.05
JWT를 적용하기 전에 알아야 할 것들  (0) 2021.03.02
Security 1. 기초 설정 ~ 로그인  (0) 2021.02.22
@Async, 비동기 기능  (0) 2021.02.16