From 2b52963f94eae83ab69b394423b255f228d01ce5 Mon Sep 17 00:00:00 2001 From: seungtaekhong Date: Tue, 3 Sep 2024 14:07:16 +0900 Subject: [PATCH] refactor: authEmail, token --- .../domain/auth/email/api/AuthEmailApi.java | 2 +- .../application/AuthEmailSendServiceImpl.java | 11 +++- .../AuthEmailVerifyServiceImpl.java | 11 ++-- .../auth/email/application/CodeGenerator.java | 11 ++-- .../auth/email/dao/AuthEmailRepository.java | 2 +- .../auth/token/application/TokenManager.java | 7 +- .../application/TokenReissueService.java | 10 +-- .../auth/token/application/TokenService.java | 12 ++-- .../auth/token/domain/RefreshToken.java | 1 + .../domain/auth/token/domain/TokenType.java | 8 +-- .../user/application/UserLoginService.java | 2 +- .../application/AuthEmailSendServiceTest.java | 58 +++++++++++------ .../AuthEmailVerifyServiceTest.java | 64 +++++++++---------- .../domain/auth/token/api/TokenApiTest.java | 35 +++++----- .../user/api/UserManagementApiTest.java | 10 +-- 15 files changed, 125 insertions(+), 119 deletions(-) diff --git a/src/main/java/com/playkuround/playkuroundserver/domain/auth/email/api/AuthEmailApi.java b/src/main/java/com/playkuround/playkuroundserver/domain/auth/email/api/AuthEmailApi.java index 6c60564d..9fd5f0fe 100644 --- a/src/main/java/com/playkuround/playkuroundserver/domain/auth/email/api/AuthEmailApi.java +++ b/src/main/java/com/playkuround/playkuroundserver/domain/auth/email/api/AuthEmailApi.java @@ -26,7 +26,7 @@ public class AuthEmailApi { @PostMapping @Operation(summary = "인증메일 전송", description = "해당 메일로 숫자 6자리의 인증 코드를 전송합니다. " + - "인증 메일 전송은 자정을 기준으로 최대 5번까지 가능합니다. 또한 인증 유효시간은 5분입니다.") + "인증 메일 전송은 자정을 기준으로 이메일당 최대 5번까지 가능합니다. 또한 인증 유효시간은 5분입니다.") public ApiResponse authEmailSend(@RequestBody @Valid AuthEmailSendRequest requestDto) { AuthEmailInfo authEmailInfo = authEmailSendService.sendAuthEmail(requestDto.getTarget().toLowerCase()); return ApiUtils.success(AuthEmailSendResponse.from(authEmailInfo)); diff --git a/src/main/java/com/playkuround/playkuroundserver/domain/auth/email/application/AuthEmailSendServiceImpl.java b/src/main/java/com/playkuround/playkuroundserver/domain/auth/email/application/AuthEmailSendServiceImpl.java index 582a4d14..70388609 100644 --- a/src/main/java/com/playkuround/playkuroundserver/domain/auth/email/application/AuthEmailSendServiceImpl.java +++ b/src/main/java/com/playkuround/playkuroundserver/domain/auth/email/application/AuthEmailSendServiceImpl.java @@ -5,6 +5,7 @@ import com.playkuround.playkuroundserver.domain.auth.email.dto.AuthEmailInfo; import com.playkuround.playkuroundserver.domain.auth.email.exception.NotKUEmailException; import com.playkuround.playkuroundserver.domain.auth.email.exception.SendingLimitExceededException; +import com.playkuround.playkuroundserver.domain.common.DateTimeService; import com.playkuround.playkuroundserver.infra.email.EmailService; import com.playkuround.playkuroundserver.infra.email.Mail; import lombok.RequiredArgsConstructor; @@ -26,6 +27,7 @@ public class AuthEmailSendServiceImpl implements AuthEmailSendService { private final EmailService emailService; private final AuthEmailRepository authEmailRepository; + private final DateTimeService dateTimeService; private final TemplateEngine templateEngine; @Value("${authentication.email.domain}") @@ -62,8 +64,9 @@ private void validateEmailDomain(String target) { } private long validateSendingCount(String target) { - LocalDateTime today = LocalDate.now().atStartOfDay(); - long sendingCount = authEmailRepository.countByTargetAndCreatedAtAfter(target, today); + LocalDate today = dateTimeService.getLocalDateNow(); + LocalDateTime startOfToday = today.atStartOfDay(); + long sendingCount = authEmailRepository.countByTargetAndCreatedAtGreaterThanEqual(target, startOfToday); if (sendingCount >= maxSendingCount) { throw new SendingLimitExceededException(); } @@ -71,7 +74,9 @@ private long validateSendingCount(String target) { } private LocalDateTime saveAuthEmail(String target, String authenticationCode) { - LocalDateTime expiredAt = LocalDateTime.now().plusSeconds(codeExpirationSeconds); + LocalDateTime now = dateTimeService.getLocalDateTimeNow(); + LocalDateTime expiredAt = now.plusSeconds(codeExpirationSeconds); + AuthEmail authEmail = AuthEmail.createAuthEmail(target, authenticationCode, expiredAt); authEmailRepository.save(authEmail); return expiredAt; diff --git a/src/main/java/com/playkuround/playkuroundserver/domain/auth/email/application/AuthEmailVerifyServiceImpl.java b/src/main/java/com/playkuround/playkuroundserver/domain/auth/email/application/AuthEmailVerifyServiceImpl.java index d9420e92..a9648b27 100644 --- a/src/main/java/com/playkuround/playkuroundserver/domain/auth/email/application/AuthEmailVerifyServiceImpl.java +++ b/src/main/java/com/playkuround/playkuroundserver/domain/auth/email/application/AuthEmailVerifyServiceImpl.java @@ -13,7 +13,7 @@ import com.playkuround.playkuroundserver.domain.auth.token.dto.TokenDto; import com.playkuround.playkuroundserver.domain.common.DateTimeService; import com.playkuround.playkuroundserver.domain.user.application.UserLoginService; -import com.playkuround.playkuroundserver.domain.user.dao.UserRepository; +import com.playkuround.playkuroundserver.domain.user.exception.UserNotFoundException; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Service; @@ -25,7 +25,6 @@ public class AuthEmailVerifyServiceImpl implements AuthEmailVerifyService { private final TokenService tokenService; - private final UserRepository userRepository; private final UserLoginService userLoginService; private final AuthEmailRepository authEmailRepository; private final DateTimeService dateTimeService; @@ -38,13 +37,11 @@ public AuthVerifyEmailResult verifyAuthEmail(String code, String email) { validateEmailAndCode(authEmail, code); authEmail.changeInvalidate(); - boolean existsUser = userRepository.existsByEmail(email); - if (existsUser) { + try { TokenDto tokenDto = userLoginService.login(email); return new TokenDtoResult(tokenDto); - } - else { - AuthVerifyToken authVerifyToken = tokenService.registerAuthVerifyToken(); + } catch (UserNotFoundException e) { + AuthVerifyToken authVerifyToken = tokenService.saveAuthVerifyToken(); return new AuthVerifyTokenResult(authVerifyToken.getAuthVerifyToken()); } } diff --git a/src/main/java/com/playkuround/playkuroundserver/domain/auth/email/application/CodeGenerator.java b/src/main/java/com/playkuround/playkuroundserver/domain/auth/email/application/CodeGenerator.java index 5f124e54..66172153 100644 --- a/src/main/java/com/playkuround/playkuroundserver/domain/auth/email/application/CodeGenerator.java +++ b/src/main/java/com/playkuround/playkuroundserver/domain/auth/email/application/CodeGenerator.java @@ -11,14 +11,11 @@ public String generateCode(Set codeTypeSet, long codeLength) { String characters = createCharacters(codeTypeSet); - StringBuilder codeBuilder = new StringBuilder(); Random random = new Random(); - for (int i = 0; i < codeLength; i++) { - int index = random.nextInt(characters.length()); - char randomChar = characters.charAt(index); - codeBuilder.append(randomChar); - } - return codeBuilder.toString(); + return random.ints(codeLength, 0, characters.length()) + .mapToObj(characters::charAt) + .collect(StringBuilder::new, StringBuilder::append, StringBuilder::append) + .toString(); } private void validateParameters(Set codeTypeSet, long codeLength) { diff --git a/src/main/java/com/playkuround/playkuroundserver/domain/auth/email/dao/AuthEmailRepository.java b/src/main/java/com/playkuround/playkuroundserver/domain/auth/email/dao/AuthEmailRepository.java index e7e121f3..f540e774 100644 --- a/src/main/java/com/playkuround/playkuroundserver/domain/auth/email/dao/AuthEmailRepository.java +++ b/src/main/java/com/playkuround/playkuroundserver/domain/auth/email/dao/AuthEmailRepository.java @@ -10,6 +10,6 @@ public interface AuthEmailRepository extends JpaRepository { Optional findFirstByTargetOrderByCreatedAtDesc(String target); - long countByTargetAndCreatedAtAfter(String target, LocalDateTime localDateTime); + long countByTargetAndCreatedAtGreaterThanEqual(String target, LocalDateTime localDateTime); } diff --git a/src/main/java/com/playkuround/playkuroundserver/domain/auth/token/application/TokenManager.java b/src/main/java/com/playkuround/playkuroundserver/domain/auth/token/application/TokenManager.java index 81fe6b02..299b2ab7 100644 --- a/src/main/java/com/playkuround/playkuroundserver/domain/auth/token/application/TokenManager.java +++ b/src/main/java/com/playkuround/playkuroundserver/domain/auth/token/application/TokenManager.java @@ -23,6 +23,7 @@ import java.security.Key; import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; import java.util.Date; import java.util.UUID; @@ -152,9 +153,9 @@ public String getTokenType(String token) { } public AuthVerifyToken createAuthVerifyTokenEntity() { - String key = UUID.randomUUID().toString(); + String token = UUID.randomUUID().toString(); LocalDateTime now = dateTimeService.getLocalDateTimeNow(); - return new AuthVerifyToken(key, now.plusSeconds(authVerifyTokenValidityInSeconds)); + return new AuthVerifyToken(token, now.plusSeconds(authVerifyTokenValidityInSeconds)); } public RefreshToken createRefreshTokenEntity(String username, String refreshToken) { @@ -162,7 +163,7 @@ public RefreshToken createRefreshTokenEntity(String username, String refreshToke return RefreshToken.builder() .userEmail(username) .refreshToken(refreshToken) - .expiredAt(now.plusSeconds(refreshTokenValidityInMilliseconds / 1000)) + .expiredAt(now.plus(refreshTokenValidityInMilliseconds, ChronoUnit.MILLIS)) .build(); } } diff --git a/src/main/java/com/playkuround/playkuroundserver/domain/auth/token/application/TokenReissueService.java b/src/main/java/com/playkuround/playkuroundserver/domain/auth/token/application/TokenReissueService.java index 5c73c26c..77bd223d 100644 --- a/src/main/java/com/playkuround/playkuroundserver/domain/auth/token/application/TokenReissueService.java +++ b/src/main/java/com/playkuround/playkuroundserver/domain/auth/token/application/TokenReissueService.java @@ -17,14 +17,14 @@ public class TokenReissueService { @Transactional public TokenDto reissue(String refreshToken) { - String username = tokenManager.getUsernameFromToken(refreshToken); - - if (!refreshTokenRepository.existsByUserEmail(username)) { + String userEmail = tokenManager.getUsernameFromToken(refreshToken); + if (!refreshTokenRepository.existsByUserEmail(userEmail)) { throw new InvalidRefreshTokenException(); } - TokenDto tokenDto = tokenManager.createTokenDto(username); - tokenService.registerRefreshToken(username, tokenDto.getRefreshToken()); + TokenDto tokenDto = tokenManager.createTokenDto(userEmail); + tokenService.saveRefreshToken(userEmail, tokenDto.getRefreshToken()); + return tokenDto; } } diff --git a/src/main/java/com/playkuround/playkuroundserver/domain/auth/token/application/TokenService.java b/src/main/java/com/playkuround/playkuroundserver/domain/auth/token/application/TokenService.java index 0ccc2128..bf32c499 100644 --- a/src/main/java/com/playkuround/playkuroundserver/domain/auth/token/application/TokenService.java +++ b/src/main/java/com/playkuround/playkuroundserver/domain/auth/token/application/TokenService.java @@ -19,22 +19,22 @@ public class TokenService { private final RefreshTokenRepository refreshTokenRepository; private final AuthVerifyTokenRepository authVerifyTokenRepository; - public void registerRefreshToken(String username, String sRefreshToken) { + public void saveRefreshToken(String username, String sRefreshToken) { refreshTokenRepository.deleteByUserEmail(username); RefreshToken refreshToken = tokenManager.createRefreshTokenEntity(username, sRefreshToken); refreshTokenRepository.save(refreshToken); } - public void deleteRefreshTokenByUser(User user) { - refreshTokenRepository.deleteByUserEmail(user.getEmail()); - } - - public AuthVerifyToken registerAuthVerifyToken() { + public AuthVerifyToken saveAuthVerifyToken() { AuthVerifyToken authVerifyToken = tokenManager.createAuthVerifyTokenEntity(); return authVerifyTokenRepository.save(authVerifyToken); } + public void deleteRefreshTokenByUser(User user) { + refreshTokenRepository.deleteByUserEmail(user.getEmail()); + } + @Transactional(readOnly = true) public void validateAuthVerifyToken(String authVerifyToken) { if (!authVerifyTokenRepository.existsByAuthVerifyToken(authVerifyToken)) { diff --git a/src/main/java/com/playkuround/playkuroundserver/domain/auth/token/domain/RefreshToken.java b/src/main/java/com/playkuround/playkuroundserver/domain/auth/token/domain/RefreshToken.java index 74f69aec..6d84d2a3 100644 --- a/src/main/java/com/playkuround/playkuroundserver/domain/auth/token/domain/RefreshToken.java +++ b/src/main/java/com/playkuround/playkuroundserver/domain/auth/token/domain/RefreshToken.java @@ -12,6 +12,7 @@ @Entity @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) +@Table(indexes = @Index(name = "idx_user_email", columnList = "userEmail")) public class RefreshToken { @Id diff --git a/src/main/java/com/playkuround/playkuroundserver/domain/auth/token/domain/TokenType.java b/src/main/java/com/playkuround/playkuroundserver/domain/auth/token/domain/TokenType.java index b2062464..32482b7b 100644 --- a/src/main/java/com/playkuround/playkuroundserver/domain/auth/token/domain/TokenType.java +++ b/src/main/java/com/playkuround/playkuroundserver/domain/auth/token/domain/TokenType.java @@ -1,11 +1,5 @@ package com.playkuround.playkuroundserver.domain.auth.token.domain; public enum TokenType { - - ACCESS, REFRESH; - - public static boolean isAccessToken(String tokenType) { - return TokenType.ACCESS.name().equals(tokenType); - } - + ACCESS, REFRESH } diff --git a/src/main/java/com/playkuround/playkuroundserver/domain/user/application/UserLoginService.java b/src/main/java/com/playkuround/playkuroundserver/domain/user/application/UserLoginService.java index 450ff82a..12796522 100644 --- a/src/main/java/com/playkuround/playkuroundserver/domain/user/application/UserLoginService.java +++ b/src/main/java/com/playkuround/playkuroundserver/domain/user/application/UserLoginService.java @@ -22,7 +22,7 @@ public TokenDto login(String userEmail) { throw new UserNotFoundException(); } TokenDto tokenDto = tokenManager.createTokenDto(userEmail); - tokenService.registerRefreshToken(userEmail, tokenDto.getRefreshToken()); + tokenService.saveRefreshToken(userEmail, tokenDto.getRefreshToken()); return tokenDto; } diff --git a/src/test/java/com/playkuround/playkuroundserver/domain/auth/email/application/AuthEmailSendServiceTest.java b/src/test/java/com/playkuround/playkuroundserver/domain/auth/email/application/AuthEmailSendServiceTest.java index 33e8ed65..d062f6dc 100644 --- a/src/test/java/com/playkuround/playkuroundserver/domain/auth/email/application/AuthEmailSendServiceTest.java +++ b/src/test/java/com/playkuround/playkuroundserver/domain/auth/email/application/AuthEmailSendServiceTest.java @@ -5,6 +5,7 @@ import com.playkuround.playkuroundserver.domain.auth.email.dto.AuthEmailInfo; import com.playkuround.playkuroundserver.domain.auth.email.exception.NotKUEmailException; import com.playkuround.playkuroundserver.domain.auth.email.exception.SendingLimitExceededException; +import com.playkuround.playkuroundserver.domain.common.DateTimeService; import com.playkuround.playkuroundserver.infra.email.EmailService; import com.playkuround.playkuroundserver.infra.email.Mail; import org.junit.jupiter.api.BeforeEach; @@ -21,6 +22,7 @@ import org.thymeleaf.TemplateEngine; import org.thymeleaf.context.Context; +import java.time.LocalDate; import java.time.LocalDateTime; import static org.assertj.core.api.Assertions.assertThat; @@ -43,43 +45,53 @@ class AuthEmailSendServiceTest { @Mock private TemplateEngine templateEngine; + @Mock + private DateTimeService dateTimeService; + + private final long codeLength = 6L; + private final long maxSendingCount = 3L; + private final String emailDomain = "test.com"; + private final long codeExpirationSeconds = 300L; + @BeforeEach void setUp() { - ReflectionTestUtils.setField(authEmailSendService, "codeLength", 6L); - ReflectionTestUtils.setField(authEmailSendService, "maxSendingCount", 3L); - ReflectionTestUtils.setField(authEmailSendService, "emailDomain", "test.com"); - ReflectionTestUtils.setField(authEmailSendService, "codeExpirationSeconds", 300L); + ReflectionTestUtils.setField(authEmailSendService, "codeLength", codeLength); + ReflectionTestUtils.setField(authEmailSendService, "maxSendingCount", maxSendingCount); + ReflectionTestUtils.setField(authEmailSendService, "emailDomain", emailDomain); + ReflectionTestUtils.setField(authEmailSendService, "codeExpirationSeconds", codeExpirationSeconds); } @Test - @DisplayName("이메일 정상 정송") + @DisplayName("숫자로 이루어진 인증 번호가 저장되고, 이메일로 전송된다.") void sendAuthEmail_1() { // given + LocalDateTime now = LocalDateTime.of(2024, 9, 3, 13, 0, 0); + when(dateTimeService.getLocalDateTimeNow()).thenReturn(now); + when(dateTimeService.getLocalDateNow()).thenReturn(now.toLocalDate()); + + String target = "test@" + emailDomain; + long sendingCount = 0; + when(authEmailRepository.countByTargetAndCreatedAtGreaterThanEqual(target, now.toLocalDate().atStartOfDay())) + .thenReturn(sendingCount); + String content = "email content"; - when(authEmailRepository.countByTargetAndCreatedAtAfter(any(String.class), any(LocalDateTime.class))) - .thenReturn(0L); when(templateEngine.process(any(String.class), any(Context.class))) .thenReturn(content); // when - String target = "test@test.com"; AuthEmailInfo result = authEmailSendService.sendAuthEmail(target); // then - assertThat(result.sendingCount()).isEqualTo(1L); + assertThat(result.sendingCount()).isEqualTo(sendingCount + 1); + assertThat(result.expiredAt()).isEqualTo(now.plusSeconds(codeExpirationSeconds)); ArgumentCaptor authEmailArgument = ArgumentCaptor.forClass(AuthEmail.class); verify(authEmailRepository, times(1)).save(authEmailArgument.capture()); AuthEmail authEmail = authEmailArgument.getValue(); assertThat(authEmail.getTarget()).isEqualTo(target); - assertThat(authEmail.getCode()).containsPattern("[0-9]{6}"); - - ArgumentCaptor mailArgument = ArgumentCaptor.forClass(Mail.class); - verify(emailService, times(1)).sendMail(mailArgument.capture()); - Mail mail = mailArgument.getValue(); - assertThat(mail.target()).isEqualTo(target); - assertThat(mail.content()).contains(content); - assertThat(mail.title()).isEqualTo("[플레이쿠라운드] 회원가입 인증코드입니다."); + assertThat(authEmail.getCode()).containsPattern("[0-9]{" + codeLength + "}"); + + verify(emailService, times(1)).sendMail(new Mail(target, "[플레이쿠라운드] 회원가입 인증코드입니다.", content)); } @ParameterizedTest @@ -94,11 +106,15 @@ void sendAuthEmail_2(String target) { @DisplayName("하루 최대 전송횟수 이상은 메일을 보낼 수 없다.") void sendAuthEmail_3() { // given - when(authEmailRepository.countByTargetAndCreatedAtAfter(any(String.class), any(LocalDateTime.class))) - .thenReturn(3L); + LocalDate today = LocalDate.of(2024, 9, 3); + when(dateTimeService.getLocalDateNow()).thenReturn(today); - // when - assertThatThrownBy(() -> authEmailSendService.sendAuthEmail("email@test.com")) + String target = "email@test.com"; + when(authEmailRepository.countByTargetAndCreatedAtGreaterThanEqual(target, today.atStartOfDay())) + .thenReturn(maxSendingCount); + + // when & then + assertThatThrownBy(() -> authEmailSendService.sendAuthEmail(target)) .isInstanceOf(SendingLimitExceededException.class); } diff --git a/src/test/java/com/playkuround/playkuroundserver/domain/auth/email/application/AuthEmailVerifyServiceTest.java b/src/test/java/com/playkuround/playkuroundserver/domain/auth/email/application/AuthEmailVerifyServiceTest.java index e336278f..2399aa38 100644 --- a/src/test/java/com/playkuround/playkuroundserver/domain/auth/email/application/AuthEmailVerifyServiceTest.java +++ b/src/test/java/com/playkuround/playkuroundserver/domain/auth/email/application/AuthEmailVerifyServiceTest.java @@ -14,8 +14,8 @@ import com.playkuround.playkuroundserver.domain.auth.token.dto.TokenDto; import com.playkuround.playkuroundserver.domain.common.DateTimeService; import com.playkuround.playkuroundserver.domain.user.application.UserLoginService; -import com.playkuround.playkuroundserver.domain.user.dao.UserRepository; import com.playkuround.playkuroundserver.domain.user.domain.User; +import com.playkuround.playkuroundserver.domain.user.exception.UserNotFoundException; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -28,7 +28,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) @@ -40,9 +39,6 @@ class AuthEmailVerifyServiceTest { @Mock private TokenService tokenService; - @Mock - private UserRepository userRepository; - @Mock private UserLoginService userLoginService; @@ -53,7 +49,7 @@ class AuthEmailVerifyServiceTest { private DateTimeService dateTimeService; @Test - @DisplayName("이메일 인증 정상 처리 : 기존회원") + @DisplayName("이메일 인증 정상 처리 : 기존회원인 경우 TokenDto 반환") void authEmailSuccessExists() { // given User user = TestUtil.createUser(); @@ -63,11 +59,8 @@ void authEmailSuccessExists() { AuthEmail authEmail = AuthEmail.createAuthEmail(target, code, expiredAt); when(authEmailRepository.findFirstByTargetOrderByCreatedAtDesc(target)) .thenReturn(Optional.of(authEmail)); - when(userRepository.existsByEmail(target)) - .thenReturn(true); when(dateTimeService.getLocalDateTimeNow()) - .thenReturn(expiredAt.minusMinutes(2)); - + .thenReturn(expiredAt.minusHours(1)); TokenDto tokenDto = new TokenDto("Bearer", "accessToken", "refreshToken", null, null); when(userLoginService.login(target)).thenReturn(tokenDto); @@ -84,7 +77,7 @@ void authEmailSuccessExists() { } @Test - @DisplayName("이메일 인증 정상 처리 : 신규회원") + @DisplayName("이메일 인증 정상 처리 : 신규회원인 경우 authVerifyToken 반환") void authEmailSuccessNewUser() { // given User user = TestUtil.createUser(); @@ -95,13 +88,13 @@ void authEmailSuccessNewUser() { AuthEmail authEmail = AuthEmail.createAuthEmail(target, code, expiredAt); when(authEmailRepository.findFirstByTargetOrderByCreatedAtDesc(target)) .thenReturn(Optional.of(authEmail)); - when(userRepository.existsByEmail(target)) - .thenReturn(false); when(dateTimeService.getLocalDateTimeNow()) - .thenReturn(expiredAt.minusMinutes(2)); + .thenReturn(expiredAt.minusHours(1)); + when(userLoginService.login(target)) + .thenThrow(UserNotFoundException.class); AuthVerifyToken authVerifyToken = new AuthVerifyToken(authVerify, null); - when(tokenService.registerAuthVerifyToken()).thenReturn(authVerifyToken); + when(tokenService.saveAuthVerifyToken()).thenReturn(authVerifyToken); // when AuthVerifyEmailResult result = authEmailVerifyService.verifyAuthEmail(code, target); @@ -113,60 +106,63 @@ void authEmailSuccessNewUser() { } @Test - @DisplayName("AuthEmail entity가 없으면 AuthEmailNotFoundException 발생") + @DisplayName("AuthEmail entity가 없으면 AuthEmailNotFoundException 발생한다.") void emptyAuthEmailEntity() { // given - when(authEmailRepository.findFirstByTargetOrderByCreatedAtDesc(any(String.class))) + String target = "test@konkuk.ac.kr"; + when(authEmailRepository.findFirstByTargetOrderByCreatedAtDesc(target)) .thenReturn(Optional.empty()); // expected - assertThatThrownBy(() -> authEmailVerifyService.verifyAuthEmail("code", "target")) + assertThatThrownBy(() -> authEmailVerifyService.verifyAuthEmail("code", target)) .isInstanceOf(AuthEmailNotFoundException.class); } @Test - @DisplayName("authEmail이 유효하지 않으면 AuthEmailNotFoundException 발생") + @DisplayName("authEmail이 유효하지 않으면 AuthEmailNotFoundException 발생한다.") void authEmailInvalidate() { // given - AuthEmail authEmail = AuthEmail.createAuthEmail("target", "code", LocalDateTime.now()); + AuthEmail authEmail = AuthEmail.createAuthEmail("test@konkuk.ac.kr", "code", LocalDateTime.now()); authEmail.changeInvalidate(); - when(authEmailRepository.findFirstByTargetOrderByCreatedAtDesc(any(String.class))) + when(authEmailRepository.findFirstByTargetOrderByCreatedAtDesc(authEmail.getTarget())) .thenReturn(Optional.of(authEmail)); // expected - assertThatThrownBy(() -> authEmailVerifyService.verifyAuthEmail("code", "target")) + assertThatThrownBy(() -> authEmailVerifyService.verifyAuthEmail(authEmail.getCode(), authEmail.getTarget())) .isInstanceOf(AuthEmailNotFoundException.class); } @Test - @DisplayName("authEmail이 만료되면 AuthCodeExpiredException 발생") + @DisplayName("authEmail이 만료되면 AuthCodeExpiredException 발생한다.") void authEmailExpired() { // given LocalDateTime now = LocalDateTime.of(2024, 7, 1, 0, 0); - AuthEmail authEmail = AuthEmail.createAuthEmail("target", "code", now.minusDays(1)); - when(authEmailRepository.findFirstByTargetOrderByCreatedAtDesc(any(String.class))) - .thenReturn(Optional.of(authEmail)); when(dateTimeService.getLocalDateTimeNow()) .thenReturn(now); + AuthEmail authEmail = AuthEmail.createAuthEmail("test@konkuk.ac.kr", "code", now.minusDays(1)); + when(authEmailRepository.findFirstByTargetOrderByCreatedAtDesc(authEmail.getTarget())) + .thenReturn(Optional.of(authEmail)); + // expected - assertThatThrownBy(() -> authEmailVerifyService.verifyAuthEmail("code", "target")) + assertThatThrownBy(() -> authEmailVerifyService.verifyAuthEmail(authEmail.getCode(), authEmail.getTarget())) .isInstanceOf(AuthCodeExpiredException.class); } @Test - @DisplayName("authEmail의 code가 일치하지 않으면 NotMatchAuthCodeException 발생") + @DisplayName("authEmail의 code가 일치하지 않으면 NotMatchAuthCodeException 발생한다.") void authEmailCodeNotEquals() { // given - String code = "code"; - AuthEmail authEmail = AuthEmail.createAuthEmail("target", code, LocalDateTime.now().plusMinutes(1)); - when(authEmailRepository.findFirstByTargetOrderByCreatedAtDesc(any(String.class))) - .thenReturn(Optional.of(authEmail)); + LocalDateTime now = LocalDateTime.now(); when(dateTimeService.getLocalDateTimeNow()) - .thenReturn(LocalDateTime.of(2024, 7, 1, 0, 0)); + .thenReturn(now); + + AuthEmail authEmail = AuthEmail.createAuthEmail("test@konkuk.ac.kr", "code", now.plusMinutes(1)); + when(authEmailRepository.findFirstByTargetOrderByCreatedAtDesc(authEmail.getTarget())) + .thenReturn(Optional.of(authEmail)); // expected - assertThatThrownBy(() -> authEmailVerifyService.verifyAuthEmail(code + "NotEqual", "target")) + assertThatThrownBy(() -> authEmailVerifyService.verifyAuthEmail(authEmail.getCode() + "NotEqual", authEmail.getTarget())) .isInstanceOf(NotMatchAuthCodeException.class); } } \ No newline at end of file diff --git a/src/test/java/com/playkuround/playkuroundserver/domain/auth/token/api/TokenApiTest.java b/src/test/java/com/playkuround/playkuroundserver/domain/auth/token/api/TokenApiTest.java index 3fc296b0..c273ab84 100644 --- a/src/test/java/com/playkuround/playkuroundserver/domain/auth/token/api/TokenApiTest.java +++ b/src/test/java/com/playkuround/playkuroundserver/domain/auth/token/api/TokenApiTest.java @@ -1,6 +1,7 @@ package com.playkuround.playkuroundserver.domain.auth.token.api; import com.fasterxml.jackson.databind.ObjectMapper; +import com.playkuround.playkuroundserver.IntegrationControllerTest; import com.playkuround.playkuroundserver.TestUtil; import com.playkuround.playkuroundserver.domain.auth.token.api.request.TokenReissueRequest; import com.playkuround.playkuroundserver.domain.auth.token.dao.RefreshTokenRepository; @@ -15,8 +16,6 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.boot.test.context.SpringBootTest; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; @@ -28,8 +27,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -@AutoConfigureMockMvc -@SpringBootTest(properties = "spring.profiles.active=test") +@IntegrationControllerTest class TokenApiTest { @Autowired @@ -49,16 +47,15 @@ class TokenApiTest { @AfterEach void clean() { - refreshTokenRepository.deleteAll(); - userRepository.deleteAll(); + refreshTokenRepository.deleteAllInBatch(); + userRepository.deleteAllInBatch(); } @Test - @DisplayName("토큰 재발급 성공") + @DisplayName("refreshToken이 유효한 상태라면, accessToken과 refreshToken이 모두 재발급된다.") void reissueSuccess() throws Exception { // given - User user = TestUtil.createUser(); - userRepository.save(user); + User user = userRepository.save(TestUtil.createUser()); TokenDto tokenDto = userLoginService.login(user.getEmail()); TokenReissueRequest tokenReissueRequest = new TokenReissueRequest(tokenDto.getRefreshToken()); @@ -67,8 +64,7 @@ void reissueSuccess() throws Exception { // expected mockMvc.perform(post("/api/auth/reissue") .contentType(MediaType.APPLICATION_JSON) - .content(request) - ) + .content(request)) .andExpect(status().isOk()) .andExpect(jsonPath("$.isSuccess").value(true)) .andExpect(jsonPath("$.response.grantType").value(GrantType.BEARER.getType())) @@ -77,7 +73,9 @@ void reissueSuccess() throws Exception { .andDo(print()); List refreshTokens = refreshTokenRepository.findAll(); - assertThat(refreshTokens.size()).isEqualTo(1); + assertThat(refreshTokens).hasSize(1) + .extracting("userEmail") + .containsExactly(user.getEmail()); } @Test @@ -90,22 +88,22 @@ void reissueFailByInvalidateRefreshToken() throws Exception { // expected mockMvc.perform(post("/api/auth/reissue") .contentType(MediaType.APPLICATION_JSON) - .content(request) - ) + .content(request)) .andExpect(status().isUnauthorized()) .andExpect(jsonPath("$.isSuccess").value(false)) .andExpect(jsonPath("$.errorResponse.code").value(ErrorCode.INVALID_TOKEN.getCode())) .andExpect(jsonPath("$.errorResponse.message").value(ErrorCode.INVALID_TOKEN.getMessage())) .andExpect(jsonPath("$.errorResponse.status").value(ErrorCode.INVALID_TOKEN.getStatus().value())) .andDo(print()); + + assertThat(refreshTokenRepository.count()).isZero(); } @Test @DisplayName("토큰 재발급 실패 : 존재하지 않는 refreshToken") void reissueFailByNotFoundRefreshToken() throws Exception { // given - User user = TestUtil.createUser(); - userRepository.save(user); + User user = userRepository.save(TestUtil.createUser()); TokenDto tokenDto = userLoginService.login(user.getEmail()); refreshTokenRepository.deleteAll(); @@ -115,13 +113,14 @@ void reissueFailByNotFoundRefreshToken() throws Exception { // expected mockMvc.perform(post("/api/auth/reissue") .contentType(MediaType.APPLICATION_JSON) - .content(request) - ) + .content(request)) .andExpect(status().isUnauthorized()) .andExpect(jsonPath("$.isSuccess").value(false)) .andExpect(jsonPath("$.errorResponse.code").value(ErrorCode.INVALID_TOKEN.getCode())) .andExpect(jsonPath("$.errorResponse.message").value(ErrorCode.INVALID_TOKEN.getMessage())) .andExpect(jsonPath("$.errorResponse.status").value(ErrorCode.INVALID_TOKEN.getStatus().value())) .andDo(print()); + + assertThat(refreshTokenRepository.count()).isZero(); } } \ No newline at end of file diff --git a/src/test/java/com/playkuround/playkuroundserver/domain/user/api/UserManagementApiTest.java b/src/test/java/com/playkuround/playkuroundserver/domain/user/api/UserManagementApiTest.java index b61fdad1..2b5b5ea0 100644 --- a/src/test/java/com/playkuround/playkuroundserver/domain/user/api/UserManagementApiTest.java +++ b/src/test/java/com/playkuround/playkuroundserver/domain/user/api/UserManagementApiTest.java @@ -69,7 +69,7 @@ void afterEach() { @DisplayName("회원 등록 성공") void userRegisterSuccess() throws Exception { // given - AuthVerifyToken authVerifyToken = tokenService.registerAuthVerifyToken(); + AuthVerifyToken authVerifyToken = tokenService.saveAuthVerifyToken(); // when UserRegisterRequest registerRequest @@ -105,7 +105,7 @@ void userRegisterSuccess() throws Exception { assertThat(user.getMajor()).isEqualTo(major); assertThat(user.getNickname()).isEqualTo(nickname); assertThat(user.getRole()).isEqualTo(Role.ROLE_USER); - assertThat(user.getAttendanceDays()).isEqualTo(0); + assertThat(user.getAttendanceDays()).isZero(); } @Test @@ -128,7 +128,7 @@ void userRegisterFailByNotExitsAuthVerifyToken() throws Exception { .andExpect(jsonPath("$.errorResponse.status").value(ErrorCode.INVALID_TOKEN.getStatus().value())) .andDo(print()); List users = userRepository.findAll(); - assertThat(users).hasSize(0); + assertThat(users).isEmpty(); } @Test @@ -137,7 +137,7 @@ void userRegisterFailByDuplicateEmail() throws Exception { // given User user = User.create(email, nickname, major, Role.ROLE_USER); userRepository.save(user); - AuthVerifyToken authVerifyToken = tokenService.registerAuthVerifyToken(); + AuthVerifyToken authVerifyToken = tokenService.saveAuthVerifyToken(); // when UserRegisterRequest registerRequest @@ -165,7 +165,7 @@ void userRegisterFailByDuplicateNickname() throws Exception { // given User user = User.create(email, nickname, major, Role.ROLE_USER); userRepository.save(user); - AuthVerifyToken authVerifyToken = tokenService.registerAuthVerifyToken(); + AuthVerifyToken authVerifyToken = tokenService.saveAuthVerifyToken(); // when UserRegisterRequest registerRequest