From 9461e937fa8265e3f8c75e2a5c8114b5bff60226 Mon Sep 17 00:00:00 2001 From: inhooo00 Date: Thu, 11 Jul 2024 03:38:37 +0900 Subject: [PATCH 01/16] =?UTF-8?q?Feat(#6):=20TokenServic=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/dto/request/RefreshTokenReqDto.java | 6 ++ .../api/dto/response/MemberLoginResDto.java | 16 +++++ .../auth/application/TokenService.java | 65 +++++++++++++++++++ 3 files changed, 87 insertions(+) create mode 100644 src/main/java/shop/kkeujeok/kkeujeokbackend/auth/api/dto/request/RefreshTokenReqDto.java create mode 100644 src/main/java/shop/kkeujeok/kkeujeokbackend/auth/api/dto/response/MemberLoginResDto.java create mode 100644 src/main/java/shop/kkeujeok/kkeujeokbackend/auth/application/TokenService.java diff --git a/src/main/java/shop/kkeujeok/kkeujeokbackend/auth/api/dto/request/RefreshTokenReqDto.java b/src/main/java/shop/kkeujeok/kkeujeokbackend/auth/api/dto/request/RefreshTokenReqDto.java new file mode 100644 index 00000000..9f67ad58 --- /dev/null +++ b/src/main/java/shop/kkeujeok/kkeujeokbackend/auth/api/dto/request/RefreshTokenReqDto.java @@ -0,0 +1,6 @@ +package shop.kkeujeok.kkeujeokbackend.auth.api.dto.request; + +public record RefreshTokenReqDto( + String refreshToken +){ +} diff --git a/src/main/java/shop/kkeujeok/kkeujeokbackend/auth/api/dto/response/MemberLoginResDto.java b/src/main/java/shop/kkeujeok/kkeujeokbackend/auth/api/dto/response/MemberLoginResDto.java new file mode 100644 index 00000000..f8073197 --- /dev/null +++ b/src/main/java/shop/kkeujeok/kkeujeokbackend/auth/api/dto/response/MemberLoginResDto.java @@ -0,0 +1,16 @@ +package shop.kkeujeok.kkeujeokbackend.auth.api.dto.response; + + +import lombok.Builder; +import shop.kkeujeok.kkeujeokbackend.member.domain.Member; + +@Builder +public record MemberLoginResDto( + Member findMember +) { + public static MemberLoginResDto from(Member member) { + return MemberLoginResDto.builder() + .findMember(member) + .build(); + } +} diff --git a/src/main/java/shop/kkeujeok/kkeujeokbackend/auth/application/TokenService.java b/src/main/java/shop/kkeujeok/kkeujeokbackend/auth/application/TokenService.java new file mode 100644 index 00000000..b0bdd2a2 --- /dev/null +++ b/src/main/java/shop/kkeujeok/kkeujeokbackend/auth/application/TokenService.java @@ -0,0 +1,65 @@ +package shop.kkeujeok.kkeujeokbackend.auth.application; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import shop.kkeujeok.kkeujeokbackend.auth.api.dto.request.RefreshTokenReqDto; +import shop.kkeujeok.kkeujeokbackend.auth.api.dto.response.MemberLoginResDto; +import shop.kkeujeok.kkeujeokbackend.global.jwt.TokenProvider; +import shop.kkeujeok.kkeujeokbackend.global.jwt.api.dto.TokenDto; +import shop.kkeujeok.kkeujeokbackend.global.jwt.domain.Token; +import shop.kkeujeok.kkeujeokbackend.global.jwt.domain.repository.TokenRepository; +import shop.kkeujeok.kkeujeokbackend.member.domain.Member; +import shop.kkeujeok.kkeujeokbackend.member.domain.repository.MemberRepository; + +@Service +@Transactional(readOnly = true) +public class TokenService { + + private final TokenProvider tokenProvider; + private final TokenRepository tokenRepository; + private final MemberRepository memberRepository; + + public TokenService(TokenProvider tokenProvider, TokenRepository tokenRepository, MemberRepository memberRepository) { + this.tokenProvider = tokenProvider; + this.tokenRepository = tokenRepository; + this.memberRepository = memberRepository; + } + + @Transactional + public TokenDto getToken(MemberLoginResDto memberLoginResDto) { + TokenDto tokenDto = tokenProvider.generateToken(memberLoginResDto.findMember().getEmail()); + + tokenSaveAndUpdate(memberLoginResDto, tokenDto); + + return tokenDto; + } + + private void tokenSaveAndUpdate(MemberLoginResDto memberLoginResDto, TokenDto tokenDto) { + if (!tokenRepository.existsByMember(memberLoginResDto.findMember())) { + tokenRepository.save(Token.builder() + .member(memberLoginResDto.findMember()) + .refreshToken(tokenDto.refreshToken()) + .build()); + } + + refreshTokenUpdate(memberLoginResDto, tokenDto); + } + + private void refreshTokenUpdate(MemberLoginResDto memberLoginResDto, TokenDto tokenDto) { + Token token = tokenRepository.findByMember(memberLoginResDto.findMember()).orElseThrow(); + token.refreshTokenUpdate(tokenDto.refreshToken()); + } + + @Transactional + public TokenDto generateAccessToken(RefreshTokenReqDto refreshTokenReqDto) { + if (!tokenRepository.existsByRefreshToken(refreshTokenReqDto.refreshToken()) || !tokenProvider.validateToken(refreshTokenReqDto.refreshToken())) { + throw new RuntimeException(); + } + + Token token = tokenRepository.findByRefreshToken(refreshTokenReqDto.refreshToken()).orElseThrow(); + Member member = memberRepository.findById(token.getMember().getMemberId()).orElseThrow(); + + return tokenProvider.generateAccessTokenByRefreshToken(member.getEmail(), token.getRefreshToken()); + } + +} From 72f1f880cb6e62269caf75dea37470318cfd6d54 Mon Sep 17 00:00:00 2001 From: inhooo00 Date: Thu, 11 Jul 2024 04:07:11 +0900 Subject: [PATCH 02/16] =?UTF-8?q?Feat(#6):=20OAuthException=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/api/dto/response/UserInfo.java | 9 +++++++++ .../global/oauth/exception/OAuthException.java | 13 +++++++++++++ src/main/resources/application.yml | 11 ++++++++++- 3 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 src/main/java/shop/kkeujeok/kkeujeokbackend/auth/api/dto/response/UserInfo.java create mode 100644 src/main/java/shop/kkeujeok/kkeujeokbackend/global/oauth/exception/OAuthException.java diff --git a/src/main/java/shop/kkeujeok/kkeujeokbackend/auth/api/dto/response/UserInfo.java b/src/main/java/shop/kkeujeok/kkeujeokbackend/auth/api/dto/response/UserInfo.java new file mode 100644 index 00000000..edd7b097 --- /dev/null +++ b/src/main/java/shop/kkeujeok/kkeujeokbackend/auth/api/dto/response/UserInfo.java @@ -0,0 +1,9 @@ +package shop.kkeujeok.kkeujeokbackend.auth.api.dto.response; + +public record UserInfo( + String email, + String name, + String picture, + String nickname +) { +} diff --git a/src/main/java/shop/kkeujeok/kkeujeokbackend/global/oauth/exception/OAuthException.java b/src/main/java/shop/kkeujeok/kkeujeokbackend/global/oauth/exception/OAuthException.java new file mode 100644 index 00000000..c54f5be5 --- /dev/null +++ b/src/main/java/shop/kkeujeok/kkeujeokbackend/global/oauth/exception/OAuthException.java @@ -0,0 +1,13 @@ +package shop.kkeujeok.kkeujeokbackend.global.oauth.exception; + +import shop.kkeujeok.kkeujeokbackend.global.error.exception.AuthGroupException; + +public class OAuthException extends AuthGroupException { + public OAuthException(String message) { + super(message); + } + + public OAuthException() { + this("OAuth 서버와의 통신 과정에서 문제가 발생했습니다."); + } +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index c5dd7057..0c4ffc98 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -28,4 +28,13 @@ token: expire: time: access : ${token.expire.time.access} - refresh : ${token.expire.time.refresh} \ No newline at end of file + refresh : ${token.expire.time.refresh} + +GOOGLE_REDIRECT_URI: ${GOOGLE_REDIRECT_URI} +client_id: ${GOOGLE_CLIENT_ID} +client_secret: ${GOOGLE_CLIENT_SECRET} + +oauth: + kakao: + rest-api-key: ${KAKAO_REST_API_KEY} + redirect-url: ${KAKAO_REDIRECT_URL} \ No newline at end of file From 2f5d341254033898165ee7f42c56f351adb37a4e Mon Sep 17 00:00:00 2001 From: inhooo00 Date: Thu, 11 Jul 2024 04:12:34 +0900 Subject: [PATCH 03/16] =?UTF-8?q?Feat(#6):=20GoogleAuthService=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/application/AuthService.java | 9 ++ .../global/oauth/GoogleAuthService.java | 99 +++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 src/main/java/shop/kkeujeok/kkeujeokbackend/auth/application/AuthService.java create mode 100644 src/main/java/shop/kkeujeok/kkeujeokbackend/global/oauth/GoogleAuthService.java diff --git a/src/main/java/shop/kkeujeok/kkeujeokbackend/auth/application/AuthService.java b/src/main/java/shop/kkeujeok/kkeujeokbackend/auth/application/AuthService.java new file mode 100644 index 00000000..06e4220e --- /dev/null +++ b/src/main/java/shop/kkeujeok/kkeujeokbackend/auth/application/AuthService.java @@ -0,0 +1,9 @@ +package shop.kkeujeok.kkeujeokbackend.auth.application; + +import shop.kkeujeok.kkeujeokbackend.auth.api.dto.response.UserInfo; + +public interface AuthService { + UserInfo getUserInfo(String authCode); + + String getProvider(); +} diff --git a/src/main/java/shop/kkeujeok/kkeujeokbackend/global/oauth/GoogleAuthService.java b/src/main/java/shop/kkeujeok/kkeujeokbackend/global/oauth/GoogleAuthService.java new file mode 100644 index 00000000..00895eaa --- /dev/null +++ b/src/main/java/shop/kkeujeok/kkeujeokbackend/global/oauth/GoogleAuthService.java @@ -0,0 +1,99 @@ +package shop.kkeujeok.kkeujeokbackend.global.oauth; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.client.RestTemplate; +import shop.kkeujeok.kkeujeokbackend.auth.api.dto.response.UserInfo; +import shop.kkeujeok.kkeujeokbackend.auth.application.AuthService; +import shop.kkeujeok.kkeujeokbackend.global.oauth.exception.OAuthException; +import shop.kkeujeok.kkeujeokbackend.member.domain.SocialType; + +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.Map; + +@Service +@Transactional(readOnly = true) +public class GoogleAuthService implements AuthService { + + private final String GOOGLE_TOKEN_URL = "https://oauth2.googleapis.com/token"; + @Value("${client_id}") + private String google_client_id; + @Value("${client_secret}") + private String google_client_secret; + + @Value("${GOOGLE_REDIRECT_URI}") + private String GOOGLE_REDIRECT_URI; + private static final String JWT_DELIMITER = "\\."; + + private final ObjectMapper objectMapper; + + public GoogleAuthService(ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + } + + + public JsonNode getGoogleIdToken(String code) { + RestTemplate restTemplate = new RestTemplate(); + Map params = Map.of( + "code", code, + "scope", "https://www.googleapis.com/auth/userinfo.profile " + + "https://www.googleapis.com/auth/userinfo.email", + "client_id", google_client_id, + "client_secret", google_client_secret, + "redirect_uri", GOOGLE_REDIRECT_URI, + "grant_type", "authorization_code" + ); + + ResponseEntity responseEntity = restTemplate.postForEntity(GOOGLE_TOKEN_URL, params, String.class); + + return parseGoogleIdToken(responseEntity); + } + + @Override + public String getProvider() { + return String.valueOf(SocialType.GOOGLE).toLowerCase(); + } + + @Transactional + @Override + public UserInfo getUserInfo(String idToken) { + String decodePayload = getDecodePayload(idToken); + + try { + return objectMapper.readValue(decodePayload, UserInfo.class); + } catch (JsonProcessingException e) { + throw new OAuthException("id 토큰을 읽을 수 없습니다."); + } + } + + private JsonNode parseGoogleIdToken(ResponseEntity responseEntity) { + if (responseEntity.getStatusCode().is2xxSuccessful()) { + String responseBody = responseEntity.getBody(); + try { + JsonNode jsonNode = objectMapper.readTree(responseBody); + return jsonNode.get("id_token"); + } catch (Exception e) { + throw new RuntimeException("ID 토큰을 파싱하는데 실패했습니다.", e); + } + } + + throw new RuntimeException("구글 엑세스 토큰을 가져오는데 실패했습니다."); + } + + private String getDecodePayload(String idToken) { + String payload = getPayload(idToken); + + return new String(Base64.getUrlDecoder().decode(payload), StandardCharsets.UTF_8); + } + + private String getPayload(String idToken) { + return idToken.split(JWT_DELIMITER)[1]; + } + +} From 9d22aca25ad9ef16f58fdbe25edc3b82c843cc4d Mon Sep 17 00:00:00 2001 From: inhooo00 Date: Thu, 11 Jul 2024 04:13:59 +0900 Subject: [PATCH 04/16] =?UTF-8?q?Feat(#6):=20KakaoAuthService=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../global/oauth/KakaoAuthService.java | 107 ++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 src/main/java/shop/kkeujeok/kkeujeokbackend/global/oauth/KakaoAuthService.java diff --git a/src/main/java/shop/kkeujeok/kkeujeokbackend/global/oauth/KakaoAuthService.java b/src/main/java/shop/kkeujeok/kkeujeokbackend/global/oauth/KakaoAuthService.java new file mode 100644 index 00000000..1a0a1950 --- /dev/null +++ b/src/main/java/shop/kkeujeok/kkeujeokbackend/global/oauth/KakaoAuthService.java @@ -0,0 +1,107 @@ +package shop.kkeujeok.kkeujeokbackend.global.oauth; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestTemplate; +import shop.kkeujeok.kkeujeokbackend.auth.api.dto.response.UserInfo; +import shop.kkeujeok.kkeujeokbackend.auth.application.AuthService; +import shop.kkeujeok.kkeujeokbackend.global.oauth.exception.OAuthException; +import shop.kkeujeok.kkeujeokbackend.member.domain.SocialType; + +import java.nio.charset.StandardCharsets; +import java.util.Base64; + +@Service +@Transactional(readOnly = true) +@Slf4j +public class KakaoAuthService implements AuthService { + + private final String KAKAO_TOKEN_URL = "https://kauth.kakao.com/oauth/token"; + @Value("${oauth.kakao.rest-api-key}") + private String restApiKey; + @Value("${oauth.kakao.redirect-url}") + private String redirectUri; + + private static final String JWT_DELIMITER = "\\."; + + private final ObjectMapper objectMapper; + + public KakaoAuthService(ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + } + + + public JsonNode getKakaoAccessToken(String code) { + RestTemplate rt = new RestTemplate(); + + HttpHeaders headers = new HttpHeaders(); + headers.add("Content-Type", "application/x-www-form-urlencoded;charset=utf-8"); + + MultiValueMap params = new LinkedMultiValueMap<>(); + params.add("grant_type", "authorization_code"); + params.add("client_id", restApiKey); + params.add("redirect_uri", redirectUri); + params.add("code", code); + + HttpEntity> kakaoTokenRequest = new HttpEntity<>(params, headers); + + ResponseEntity response = rt.exchange( + KAKAO_TOKEN_URL, + HttpMethod.POST, + kakaoTokenRequest, + String.class + ); + + + if (response.getStatusCode().is2xxSuccessful()) { + String responseBody = response.getBody(); + try { + JsonNode jsonNode = objectMapper.readTree(responseBody); + return jsonNode.get("id_token"); + } catch (Exception e) { + throw new RuntimeException("ID 토큰을 파싱하는데 실패했습니다.", e); + } + } + throw new RuntimeException("구글 엑세스 토큰을 가져오는데 실패했습니다."); + + } + + @Override + public String getProvider() { + return String.valueOf(SocialType.KAKAO).toLowerCase(); + } + + @Transactional + @Override + public UserInfo getUserInfo(String idToken) { + String decodePayload = getDecodePayload(idToken); + + try { + return objectMapper.readValue(decodePayload, UserInfo.class); + } catch (JsonProcessingException e) { + throw new OAuthException("id 토큰을 읽을 수 없습니다."); + } + } + + private String getDecodePayload(String idToken) { + String payload = getPayload(idToken); + + return new String(Base64.getUrlDecoder().decode(payload), StandardCharsets.UTF_8); + } + + private String getPayload(String idToken) { + return idToken.split(JWT_DELIMITER)[1]; + } + +} From eb2c213a681a50004de8df900bb7109196146063 Mon Sep 17 00:00:00 2001 From: inhooo00 Date: Fri, 12 Jul 2024 02:24:25 +0900 Subject: [PATCH 05/16] =?UTF-8?q?Feat(#6):=20AuthServiceFactory=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/application/AuthServiceFactory.java | 25 +++++++++++++++++++ .../global/oauth/GoogleAuthServiceTest.java | 4 +++ 2 files changed, 29 insertions(+) create mode 100644 src/main/java/shop/kkeujeok/kkeujeokbackend/auth/application/AuthServiceFactory.java create mode 100644 src/test/java/shop/kkeujeok/kkeujeokbackend/global/oauth/GoogleAuthServiceTest.java diff --git a/src/main/java/shop/kkeujeok/kkeujeokbackend/auth/application/AuthServiceFactory.java b/src/main/java/shop/kkeujeok/kkeujeokbackend/auth/application/AuthServiceFactory.java new file mode 100644 index 00000000..a6a34533 --- /dev/null +++ b/src/main/java/shop/kkeujeok/kkeujeokbackend/auth/application/AuthServiceFactory.java @@ -0,0 +1,25 @@ +package shop.kkeujeok.kkeujeokbackend.auth.application; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service +public class AuthServiceFactory { + private final Map authServiceMap; + + @Autowired + public AuthServiceFactory(List authServiceList) { + authServiceMap = new HashMap<>(); + for (AuthService authService : authServiceList) { + authServiceMap.put(authService.getProvider(), authService); + } + } + + public AuthService getAuthService(String provider) { + return authServiceMap.get(provider); + } +} diff --git a/src/test/java/shop/kkeujeok/kkeujeokbackend/global/oauth/GoogleAuthServiceTest.java b/src/test/java/shop/kkeujeok/kkeujeokbackend/global/oauth/GoogleAuthServiceTest.java new file mode 100644 index 00000000..5dd80b20 --- /dev/null +++ b/src/test/java/shop/kkeujeok/kkeujeokbackend/global/oauth/GoogleAuthServiceTest.java @@ -0,0 +1,4 @@ +package shop.kkeujeok.kkeujeokbackend.global.oauth; + +public class GoogleAuthServiceTest { +} From 3f7624cf53d38d1bb4b1c1681b8bb254166f32c7 Mon Sep 17 00:00:00 2001 From: inhooo00 Date: Fri, 12 Jul 2024 02:25:25 +0900 Subject: [PATCH 06/16] =?UTF-8?q?Feat(#6):=20=ED=86=A0=ED=81=B0=20?= =?UTF-8?q?=EC=9D=91=EB=8B=B5/=EB=B0=98=ED=99=98=20DTO=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/api/dto/request/TokenReqDto.java | 6 ++++++ .../api/dto/response/AccessAndRefreshTokenResDto.java | 10 ++++++++++ 2 files changed, 16 insertions(+) create mode 100644 src/main/java/shop/kkeujeok/kkeujeokbackend/auth/api/dto/request/TokenReqDto.java create mode 100644 src/main/java/shop/kkeujeok/kkeujeokbackend/auth/api/dto/response/AccessAndRefreshTokenResDto.java diff --git a/src/main/java/shop/kkeujeok/kkeujeokbackend/auth/api/dto/request/TokenReqDto.java b/src/main/java/shop/kkeujeok/kkeujeokbackend/auth/api/dto/request/TokenReqDto.java new file mode 100644 index 00000000..42a86934 --- /dev/null +++ b/src/main/java/shop/kkeujeok/kkeujeokbackend/auth/api/dto/request/TokenReqDto.java @@ -0,0 +1,6 @@ +package shop.kkeujeok.kkeujeokbackend.auth.api.dto.request; + +public record TokenReqDto( + String authCode +) { +} diff --git a/src/main/java/shop/kkeujeok/kkeujeokbackend/auth/api/dto/response/AccessAndRefreshTokenResDto.java b/src/main/java/shop/kkeujeok/kkeujeokbackend/auth/api/dto/response/AccessAndRefreshTokenResDto.java new file mode 100644 index 00000000..b6e375b8 --- /dev/null +++ b/src/main/java/shop/kkeujeok/kkeujeokbackend/auth/api/dto/response/AccessAndRefreshTokenResDto.java @@ -0,0 +1,10 @@ +package shop.kkeujeok.kkeujeokbackend.auth.api.dto.response; + +import lombok.Builder; + +@Builder +public record AccessAndRefreshTokenResDto( + String accessToken, + String refreshToken +) { +} From 0bfba3cab341ef94effbf46c16804c72e81d6889 Mon Sep 17 00:00:00 2001 From: inhooo00 Date: Fri, 12 Jul 2024 02:26:02 +0900 Subject: [PATCH 07/16] =?UTF-8?q?Feat(#6):=20AuthMemberService=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/application/AuthMemberService.java | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 src/main/java/shop/kkeujeok/kkeujeokbackend/auth/application/AuthMemberService.java diff --git a/src/main/java/shop/kkeujeok/kkeujeokbackend/auth/application/AuthMemberService.java b/src/main/java/shop/kkeujeok/kkeujeokbackend/auth/application/AuthMemberService.java new file mode 100644 index 00000000..92d617be --- /dev/null +++ b/src/main/java/shop/kkeujeok/kkeujeokbackend/auth/application/AuthMemberService.java @@ -0,0 +1,83 @@ +package shop.kkeujeok.kkeujeokbackend.auth.application; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import shop.kkeujeok.kkeujeokbackend.auth.api.dto.response.MemberLoginResDto; +import shop.kkeujeok.kkeujeokbackend.auth.api.dto.response.UserInfo; +import shop.kkeujeok.kkeujeokbackend.member.domain.Member; +import shop.kkeujeok.kkeujeokbackend.member.domain.Role; +import shop.kkeujeok.kkeujeokbackend.member.domain.SocialType; +import shop.kkeujeok.kkeujeokbackend.member.domain.repository.MemberRepository; + +import java.util.Optional; + +@Service +@Transactional(readOnly = true) +public class AuthMemberService { + private final MemberRepository memberRepository; + + public AuthMemberService(MemberRepository memberRepository) { + this.memberRepository = memberRepository; + } + + @Transactional + public MemberLoginResDto saveUserInfo(UserInfo userInfo, SocialType provider) { + validateNotFoundEmail(userInfo.email()); + + Member member = getExistingMemberOrCreateNew(userInfo, provider); + + validateSocialType(member, provider); + + return MemberLoginResDto.from(member); + } + + private void validateNotFoundEmail(String email) { + if (email == null) { + throw new RuntimeException(); + } + } + + private Member getExistingMemberOrCreateNew(UserInfo userInfo, SocialType provider) { + return memberRepository.findByEmail(userInfo.email()).orElseGet(() -> createMember(userInfo, provider)); + } + + private Member createMember(UserInfo userInfo, SocialType provider) { + String userPicture = getUserPicture(userInfo.picture()); + String name = userInfo.name(); + String nickname = userInfo.nickname(); + + if (name == null && nickname != null) { + name = nickname; + } else if (nickname == null && name != null) { + nickname = name; + } + + return memberRepository.save( + Member.builder() + .email(userInfo.email()) + .name(name) + .picture(userPicture) + .socialType(provider) + .role(Role.ROLE_USER) + .firstLogin(true) + .nickname(nickname) + .build() + ); + } + + private String getUserPicture(String picture) { + return Optional.ofNullable(picture) + .map(this::convertToHighRes).orElseThrow(); + } + + private String convertToHighRes(String url){ + return url.replace("s96-c", "s2048-c"); + } + + private void validateSocialType(Member member, SocialType provider) { + if (!provider.equals(member.getSocialType())) { + throw new RuntimeException(); + } + } + +} From e5821f82f33c4fc134a2a597e7722aacb2bc88c9 Mon Sep 17 00:00:00 2001 From: inhooo00 Date: Fri, 12 Jul 2024 02:26:22 +0900 Subject: [PATCH 08/16] =?UTF-8?q?Feat(#6):=20AuthController=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/api/AuthController.java | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 src/main/java/shop/kkeujeok/kkeujeokbackend/auth/api/AuthController.java diff --git a/src/main/java/shop/kkeujeok/kkeujeokbackend/auth/api/AuthController.java b/src/main/java/shop/kkeujeok/kkeujeokbackend/auth/api/AuthController.java new file mode 100644 index 00000000..328d2c3e --- /dev/null +++ b/src/main/java/shop/kkeujeok/kkeujeokbackend/auth/api/AuthController.java @@ -0,0 +1,66 @@ +package shop.kkeujeok.kkeujeokbackend.auth.api; + +import com.fasterxml.jackson.databind.JsonNode; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.*; +import shop.kkeujeok.kkeujeokbackend.auth.api.dto.request.RefreshTokenReqDto; +import shop.kkeujeok.kkeujeokbackend.auth.api.dto.request.TokenReqDto; +import shop.kkeujeok.kkeujeokbackend.auth.api.dto.response.MemberLoginResDto; +import shop.kkeujeok.kkeujeokbackend.auth.api.dto.response.UserInfo; +import shop.kkeujeok.kkeujeokbackend.auth.application.AuthMemberService; +import shop.kkeujeok.kkeujeokbackend.auth.application.AuthService; +import shop.kkeujeok.kkeujeokbackend.auth.application.AuthServiceFactory; +import shop.kkeujeok.kkeujeokbackend.auth.application.TokenService; +import shop.kkeujeok.kkeujeokbackend.global.jwt.api.dto.TokenDto; +import shop.kkeujeok.kkeujeokbackend.global.oauth.GoogleAuthService; +import shop.kkeujeok.kkeujeokbackend.global.oauth.KakaoAuthService; +import shop.kkeujeok.kkeujeokbackend.global.template.RspTemplate; +import shop.kkeujeok.kkeujeokbackend.member.domain.SocialType; + +@RestController +@Slf4j +@RequestMapping("/api") +@RequiredArgsConstructor +public class AuthController { + private final AuthServiceFactory authServiceFactory; + private final AuthMemberService memberService; + private final TokenService tokenService; + private final GoogleAuthService getGoogleAccessToken; + private final KakaoAuthService kakaoAuthService; + + @GetMapping("oauth2/callback/google") + public JsonNode googleCallback(@RequestParam(name = "code") String code) { + return getGoogleAccessToken.getGoogleIdToken(code); + } + + @GetMapping("oauth2/callback/kakao") + public JsonNode kakaoCallback(@RequestParam(name = "code") String code) { + return kakaoAuthService.getKakaoAccessToken(code); + } + +// @Operation(summary = "로그인 후 토큰 발급", description = "액세스, 리프레쉬 토큰을 발급합니다.") + @PostMapping("/{provider}/token") + public RspTemplate generateAccessAndRefreshToken( + @PathVariable(name = "provider") String provider, + @RequestBody TokenReqDto tokenReqDto) { + AuthService authService = authServiceFactory.getAuthService(provider); + UserInfo userInfo = authService.getUserInfo(tokenReqDto.authCode()); + + MemberLoginResDto getMemberDto = memberService.saveUserInfo(userInfo, + SocialType.valueOf(provider.toUpperCase())); + TokenDto getToken = tokenService.getToken(getMemberDto); + + return new RspTemplate<>(HttpStatus.OK, "토큰 발급", getToken); + } + +// @Operation(summary = "액세스 토큰 재발급", description = "리프레쉬 토큰으로 액세스 토큰을 발급합니다.") + @PostMapping("/token/access") + public RspTemplate generateAccessToken(@RequestBody RefreshTokenReqDto refreshTokenReqDto) { + TokenDto getToken = tokenService.generateAccessToken(refreshTokenReqDto); + + return new RspTemplate<>(HttpStatus.OK, "액세스 토큰 발급", getToken); + } + +} From 634ce27b2865800e0ced4b5bf611ae19dba310bc Mon Sep 17 00:00:00 2001 From: inhooo00 Date: Fri, 12 Jul 2024 14:31:12 +0900 Subject: [PATCH 09/16] =?UTF-8?q?Feat(#6):=20Member=EC=97=90=20BaseEntity?= =?UTF-8?q?=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 -- .../auth/application/AuthMemberService.java | 2 ++ .../auth/application/TokenService.java | 2 +- .../kkeujeokbackend/member/domain/Member.java | 14 +++++++------- src/main/resources/application.yml | 2 +- .../repository/MemberRepositoryTest.java | 18 ++++++++++++++++++ 6 files changed, 29 insertions(+), 11 deletions(-) create mode 100644 src/test/java/shop/kkeujeok/kkeujeokbackend/member/domain/repository/MemberRepositoryTest.java diff --git a/build.gradle b/build.gradle index 46f875ea..7beb4c1a 100644 --- a/build.gradle +++ b/build.gradle @@ -43,8 +43,6 @@ dependencies { implementation 'io.jsonwebtoken:jjwt-api:0.11.5' runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5' runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.11.5' - - } tasks.named('test') { diff --git a/src/main/java/shop/kkeujeok/kkeujeokbackend/auth/application/AuthMemberService.java b/src/main/java/shop/kkeujeok/kkeujeokbackend/auth/application/AuthMemberService.java index 92d617be..707e90e3 100644 --- a/src/main/java/shop/kkeujeok/kkeujeokbackend/auth/application/AuthMemberService.java +++ b/src/main/java/shop/kkeujeok/kkeujeokbackend/auth/application/AuthMemberService.java @@ -4,6 +4,7 @@ import org.springframework.transaction.annotation.Transactional; import shop.kkeujeok.kkeujeokbackend.auth.api.dto.response.MemberLoginResDto; import shop.kkeujeok.kkeujeokbackend.auth.api.dto.response.UserInfo; +import shop.kkeujeok.kkeujeokbackend.global.entity.Status; import shop.kkeujeok.kkeujeokbackend.member.domain.Member; import shop.kkeujeok.kkeujeokbackend.member.domain.Role; import shop.kkeujeok.kkeujeokbackend.member.domain.SocialType; @@ -54,6 +55,7 @@ private Member createMember(UserInfo userInfo, SocialType provider) { return memberRepository.save( Member.builder() + .status(Status.A) .email(userInfo.email()) .name(name) .picture(userPicture) diff --git a/src/main/java/shop/kkeujeok/kkeujeokbackend/auth/application/TokenService.java b/src/main/java/shop/kkeujeok/kkeujeokbackend/auth/application/TokenService.java index b0bdd2a2..4a67bd8f 100644 --- a/src/main/java/shop/kkeujeok/kkeujeokbackend/auth/application/TokenService.java +++ b/src/main/java/shop/kkeujeok/kkeujeokbackend/auth/application/TokenService.java @@ -57,7 +57,7 @@ public TokenDto generateAccessToken(RefreshTokenReqDto refreshTokenReqDto) { } Token token = tokenRepository.findByRefreshToken(refreshTokenReqDto.refreshToken()).orElseThrow(); - Member member = memberRepository.findById(token.getMember().getMemberId()).orElseThrow(); + Member member = memberRepository.findById(token.getMember().getId()).orElseThrow(); return tokenProvider.generateAccessTokenByRefreshToken(member.getEmail(), token.getRefreshToken()); } diff --git a/src/main/java/shop/kkeujeok/kkeujeokbackend/member/domain/Member.java b/src/main/java/shop/kkeujeok/kkeujeokbackend/member/domain/Member.java index f55f487e..4492662d 100644 --- a/src/main/java/shop/kkeujeok/kkeujeokbackend/member/domain/Member.java +++ b/src/main/java/shop/kkeujeok/kkeujeokbackend/member/domain/Member.java @@ -5,16 +5,16 @@ import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import shop.kkeujeok.kkeujeokbackend.global.entity.BaseEntity; +import shop.kkeujeok.kkeujeokbackend.global.entity.Status; @Entity @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) -public class Member { +public class Member extends BaseEntity { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "member_id") - private Long memberId; + @Enumerated(EnumType.STRING) + private Status status; private boolean firstLogin; @@ -34,9 +34,9 @@ public class Member { private String nickname; - @Builder - private Member(Role role, String email, String name, String picture, SocialType socialType, boolean firstLogin, String nickname) { + private Member(Status status, Role role, String email, String name, String picture, SocialType socialType, boolean firstLogin, String nickname) { + this.status = status; this.role = role; this.email = email; this.name = name; diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 0609bd1c..cc692cda 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -10,7 +10,7 @@ spring: jpa: hibernate: - ddl-auto: update + ddl-auto: create properties: hibernate: show_sql: true diff --git a/src/test/java/shop/kkeujeok/kkeujeokbackend/member/domain/repository/MemberRepositoryTest.java b/src/test/java/shop/kkeujeok/kkeujeokbackend/member/domain/repository/MemberRepositoryTest.java new file mode 100644 index 00000000..ec8e314b --- /dev/null +++ b/src/test/java/shop/kkeujeok/kkeujeokbackend/member/domain/repository/MemberRepositoryTest.java @@ -0,0 +1,18 @@ +package shop.kkeujeok.kkeujeokbackend.member.domain.repository; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import shop.kkeujeok.kkeujeokbackend.member.domain.Member; + +public class MemberRepositoryTest { + + private final MemberRepository memberRepository; + + public MemberRepositoryTest(MemberRepository memberRepository) { this.memberRepository = memberRepository;} + + @DisplayName("이메일을 통해 회원을 찾는다.") + @Test + void 이메일을_통해_회원을_찾는다() { +// Member 끄적 = memberRepository. + } +} From 5b5532280c97471f2f6dae6122663c243e2ab30b Mon Sep 17 00:00:00 2001 From: inhooo00 Date: Sun, 14 Jul 2024 00:05:58 +0900 Subject: [PATCH 10/16] =?UTF-8?q?Feat(#20):=20tokenService=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../global/jwt/domain/Token.java | 2 +- .../kkeujeokbackend/member/domain/Member.java | 4 +- src/main/resources/application.yml | 2 +- .../auth/application/TokenServiceTest.java | 105 ++++++++++++++++++ .../global/jwt/domain/TokenTest.java | 28 +++++ .../repository/MemberRepositoryTest.java | 48 +++++--- 6 files changed, 166 insertions(+), 23 deletions(-) create mode 100644 src/test/java/shop/kkeujeok/kkeujeokbackend/auth/application/TokenServiceTest.java create mode 100644 src/test/java/shop/kkeujeok/kkeujeokbackend/global/jwt/domain/TokenTest.java diff --git a/src/main/java/shop/kkeujeok/kkeujeokbackend/global/jwt/domain/Token.java b/src/main/java/shop/kkeujeok/kkeujeokbackend/global/jwt/domain/Token.java index fcb7a27a..a9b43785 100644 --- a/src/main/java/shop/kkeujeok/kkeujeokbackend/global/jwt/domain/Token.java +++ b/src/main/java/shop/kkeujeok/kkeujeokbackend/global/jwt/domain/Token.java @@ -24,7 +24,7 @@ public class Token { private String refreshToken; @Builder - private Token(Member member, String refreshToken) { + public Token(Member member, String refreshToken) { this.member = member; this.refreshToken = refreshToken; } diff --git a/src/main/java/shop/kkeujeok/kkeujeokbackend/member/domain/Member.java b/src/main/java/shop/kkeujeok/kkeujeokbackend/member/domain/Member.java index 4492662d..904172c2 100644 --- a/src/main/java/shop/kkeujeok/kkeujeokbackend/member/domain/Member.java +++ b/src/main/java/shop/kkeujeok/kkeujeokbackend/member/domain/Member.java @@ -10,7 +10,7 @@ @Entity @Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) +@NoArgsConstructor public class Member extends BaseEntity { @Enumerated(EnumType.STRING) @@ -30,10 +30,8 @@ public class Member extends BaseEntity { @Enumerated(value = EnumType.STRING) private SocialType socialType; - // @Schema(description = "닉네임", example = "웅이") private String nickname; - @Builder private Member(Status status, Role role, String email, String name, String picture, SocialType socialType, boolean firstLogin, String nickname) { this.status = status; diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index cc692cda..0609bd1c 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -10,7 +10,7 @@ spring: jpa: hibernate: - ddl-auto: create + ddl-auto: update properties: hibernate: show_sql: true diff --git a/src/test/java/shop/kkeujeok/kkeujeokbackend/auth/application/TokenServiceTest.java b/src/test/java/shop/kkeujeok/kkeujeokbackend/auth/application/TokenServiceTest.java new file mode 100644 index 00000000..28a937fa --- /dev/null +++ b/src/test/java/shop/kkeujeok/kkeujeokbackend/auth/application/TokenServiceTest.java @@ -0,0 +1,105 @@ +package shop.kkeujeok.kkeujeokbackend.auth.application; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import shop.kkeujeok.kkeujeokbackend.auth.api.dto.request.RefreshTokenReqDto; +import shop.kkeujeok.kkeujeokbackend.auth.api.dto.response.MemberLoginResDto; +import shop.kkeujeok.kkeujeokbackend.global.jwt.TokenProvider; +import shop.kkeujeok.kkeujeokbackend.global.jwt.api.dto.TokenDto; +import shop.kkeujeok.kkeujeokbackend.global.jwt.domain.Token; +import shop.kkeujeok.kkeujeokbackend.global.jwt.domain.repository.TokenRepository; +import shop.kkeujeok.kkeujeokbackend.member.domain.Member; +import shop.kkeujeok.kkeujeokbackend.member.domain.repository.MemberRepository; + +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class TokenServiceTest { + + @Mock + private TokenProvider tokenProvider; + + @Mock + private TokenRepository tokenRepository; + + @Mock + private MemberRepository memberRepository; + + @InjectMocks + private TokenService tokenService; + + private MemberLoginResDto memberLoginResDto; + private TokenDto tokenDto; + private Member member; + private Token token; + + @BeforeEach + void setUp() { + member = Member.builder().email("test@example.com").build(); + + memberLoginResDto = mock(MemberLoginResDto.class); + tokenDto = mock(TokenDto.class); + token = mock(Token.class); + + when(memberLoginResDto.findMember()).thenReturn(member); + when(tokenProvider.generateToken(anyString())).thenReturn(tokenDto); + when(tokenRepository.findByMember(any(Member.class))).thenReturn(Optional.of(token)); + when(tokenDto.refreshToken()).thenReturn("new-refresh-token"); + } + + @DisplayName("accessToken과 refreshToken을 생성한다.") + @Test + void accessToken과_refreshToken을_생성한다() { + when(tokenRepository.existsByMember(any(Member.class))).thenReturn(false); + + TokenDto result = tokenService.getToken(memberLoginResDto); + + assertNotNull(result); + verify(tokenProvider).generateToken(member.getEmail()); + verify(tokenRepository).existsByMember(member); + verify(tokenRepository).save(any(Token.class)); + verify(token).refreshTokenUpdate("new-refresh-token"); + } + +// 하다가 벽느낀 테스트. +// @DisplayName("refreshToken으로 accessToken를 재생성한다.") +// @Test +// void refreshToken으로_accessToken를_재생성한다.() { +// // given +// String refreshToken = "refresh-token"; +// RefreshTokenReqDto refreshTokenReqDto = new RefreshTokenReqDto(refreshToken); +// Token token = new Token(member, refreshToken); +// +// when(tokenRepository.existsByRefreshToken(refreshToken)).thenReturn(true); +// when(tokenProvider.validateToken(refreshToken)).thenReturn(true); +// when(tokenRepository.findByRefreshToken(refreshToken)).thenReturn(Optional.of(token)); +// // Here we mock the memberRepository.findById to handle null or any Long +// when(memberRepository.findById(anyLong())).thenAnswer(invocation -> { +// Long id = invocation.getArgument(0); +// return id == null ? Optional.empty() : Optional.of(member); +// }); +// when(tokenProvider.generateAccessTokenByRefreshToken(anyString(), anyString())).thenReturn(tokenDto); +// +// // when +// TokenDto result = tokenService.generateAccessToken(refreshTokenReqDto); +// +// // then +// assertNotNull(result); +// verify(tokenRepository).existsByRefreshToken(refreshToken); +// verify(tokenProvider).validateToken(refreshToken); +// verify(tokenRepository).findByRefreshToken(refreshToken); +// verify(memberRepository).findById(anyLong()); +// verify(tokenProvider).generateAccessTokenByRefreshToken(member.getEmail(), refreshToken); +// } +} diff --git a/src/test/java/shop/kkeujeok/kkeujeokbackend/global/jwt/domain/TokenTest.java b/src/test/java/shop/kkeujeok/kkeujeokbackend/global/jwt/domain/TokenTest.java new file mode 100644 index 00000000..9e32a868 --- /dev/null +++ b/src/test/java/shop/kkeujeok/kkeujeokbackend/global/jwt/domain/TokenTest.java @@ -0,0 +1,28 @@ +package shop.kkeujeok.kkeujeokbackend.global.jwt.domain; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import shop.kkeujeok.kkeujeokbackend.member.domain.Member; + +import static org.assertj.core.api.Assertions.assertThat; + +public class TokenTest { + @DisplayName("refresh token을 교체한다.") + @Test + void refresh_token을_교체한다() { + // given + Member 인호 = new Member(); + String refreshToken = "adasaegsfadasdasfgfgrgredksgdffa"; + Token oAuthToken = new Token(인호, refreshToken); + + String updatedRefreshToken = "dfgsbnskjglnafgkajfnakfjgngejlkrqgn"; + + // when + oAuthToken.refreshTokenUpdate(updatedRefreshToken); + + // then + assertThat(oAuthToken.getRefreshToken()).isEqualTo(updatedRefreshToken); + } + + +} diff --git a/src/test/java/shop/kkeujeok/kkeujeokbackend/member/domain/repository/MemberRepositoryTest.java b/src/test/java/shop/kkeujeok/kkeujeokbackend/member/domain/repository/MemberRepositoryTest.java index ec8e314b..2cd541a1 100644 --- a/src/test/java/shop/kkeujeok/kkeujeokbackend/member/domain/repository/MemberRepositoryTest.java +++ b/src/test/java/shop/kkeujeok/kkeujeokbackend/member/domain/repository/MemberRepositoryTest.java @@ -1,18 +1,30 @@ -package shop.kkeujeok.kkeujeokbackend.member.domain.repository; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import shop.kkeujeok.kkeujeokbackend.member.domain.Member; - -public class MemberRepositoryTest { - - private final MemberRepository memberRepository; - - public MemberRepositoryTest(MemberRepository memberRepository) { this.memberRepository = memberRepository;} - - @DisplayName("이메일을 통해 회원을 찾는다.") - @Test - void 이메일을_통해_회원을_찾는다() { -// Member 끄적 = memberRepository. - } -} +//package shop.kkeujeok.kkeujeokbackend.member.domain.repository; +// +//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.orm.jpa.DataJpaTest; +//import org.springframework.transaction.annotation.Transactional; +//import shop.kkeujeok.kkeujeokbackend.member.domain.Member; +// +//import static org.assertj.core.api.Assertions.assertThat; +// +//@DataJpaTest +//public class MemberRepositoryTest { +// +// @Autowired +// private MemberRepository memberRepository; +// +// @DisplayName("이메일을 통해 회원을 찾는다.") +// @Test +// @Transactional +// void 이메일을_통해_회원을_찾는다() { +// Member 끄적 = Member.builder() +// .email("끄적_이메일") +// .build(); +// +// memberRepository.save(끄적); +// +// assertThat(memberRepository.findByEmail("끄적_이메일").get().getId()).isEqualTo(끄적.getId()); +// } +//} From b6fca970137382b4e66b4e9227927b00db2b18fc Mon Sep 17 00:00:00 2001 From: inhooo00 Date: Sun, 14 Jul 2024 00:17:23 +0900 Subject: [PATCH 11/16] =?UTF-8?q?Feat(#20):=20MemberRepository=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/MemberRepositoryTest.java | 69 +++++++++++-------- 1 file changed, 39 insertions(+), 30 deletions(-) diff --git a/src/test/java/shop/kkeujeok/kkeujeokbackend/member/domain/repository/MemberRepositoryTest.java b/src/test/java/shop/kkeujeok/kkeujeokbackend/member/domain/repository/MemberRepositoryTest.java index 2cd541a1..988666e0 100644 --- a/src/test/java/shop/kkeujeok/kkeujeokbackend/member/domain/repository/MemberRepositoryTest.java +++ b/src/test/java/shop/kkeujeok/kkeujeokbackend/member/domain/repository/MemberRepositoryTest.java @@ -1,30 +1,39 @@ -//package shop.kkeujeok.kkeujeokbackend.member.domain.repository; -// -//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.orm.jpa.DataJpaTest; -//import org.springframework.transaction.annotation.Transactional; -//import shop.kkeujeok.kkeujeokbackend.member.domain.Member; -// -//import static org.assertj.core.api.Assertions.assertThat; -// -//@DataJpaTest -//public class MemberRepositoryTest { -// -// @Autowired -// private MemberRepository memberRepository; -// -// @DisplayName("이메일을 통해 회원을 찾는다.") -// @Test -// @Transactional -// void 이메일을_통해_회원을_찾는다() { -// Member 끄적 = Member.builder() -// .email("끄적_이메일") -// .build(); -// -// memberRepository.save(끄적); -// -// assertThat(memberRepository.findByEmail("끄적_이메일").get().getId()).isEqualTo(끄적.getId()); -// } -//} +package shop.kkeujeok.kkeujeokbackend.member.domain.repository; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import shop.kkeujeok.kkeujeokbackend.member.domain.Member; + +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class MemberRepositoryTest { + + @Mock + private MemberRepository memberRepository; + + @Test + void testFindByEmail() { + // given + String email = "test@example.com"; + Member member = Member.builder() + .email(email) + .build(); + + when(memberRepository.findByEmail(anyString())).thenReturn(Optional.of(member)); + + // when + Optional foundMember = memberRepository.findByEmail(email); + + // then + assertThat(foundMember).isPresent(); + assertThat(foundMember.get().getEmail()).isEqualTo(email); + } +} From a37c20d657af4e656dd75fa015001598c7814ee6 Mon Sep 17 00:00:00 2001 From: inhooo00 Date: Sun, 14 Jul 2024 01:00:48 +0900 Subject: [PATCH 12/16] =?UTF-8?q?Feat(#20):=20TokenRepository=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/TokenRepositoryTest.java | 91 +++++++++++++++++++ .../repository/MemberRepositoryTest.java | 4 +- 2 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 src/test/java/shop/kkeujeok/kkeujeokbackend/global/jwt/domain/repository/TokenRepositoryTest.java diff --git a/src/test/java/shop/kkeujeok/kkeujeokbackend/global/jwt/domain/repository/TokenRepositoryTest.java b/src/test/java/shop/kkeujeok/kkeujeokbackend/global/jwt/domain/repository/TokenRepositoryTest.java new file mode 100644 index 00000000..d487ea94 --- /dev/null +++ b/src/test/java/shop/kkeujeok/kkeujeokbackend/global/jwt/domain/repository/TokenRepositoryTest.java @@ -0,0 +1,91 @@ +package shop.kkeujeok.kkeujeokbackend.global.jwt.domain.repository; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import shop.kkeujeok.kkeujeokbackend.global.jwt.domain.Token; +import shop.kkeujeok.kkeujeokbackend.member.domain.Member; + +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class TokenRepositoryTest { + + @Mock + private TokenRepository tokenRepository; + + private Member member; + private Token token; + + @BeforeEach + void setUp() { + member = Member.builder().email("test@example.com").build(); + token = Token.builder().member(member).refreshToken("refresh-token").build(); + } + + @DisplayName("member로 token이 존재하는지 확인한다.") + + @Test + void member로_token이_존재하는지_확인한다() { + // given + when(tokenRepository.existsByMember(any(Member.class))).thenReturn(true); + + // when + boolean exists = tokenRepository.existsByMember(member); + + // then + assertThat(exists).isTrue(); + } + + @DisplayName("member로 token을 찾는다.") + + @Test + void member로_token을_찾는다() { + // given + when(tokenRepository.findByMember(any(Member.class))).thenReturn(Optional.of(token)); + + // when + Optional foundToken = tokenRepository.findByMember(member); + + // then + assertThat(foundToken).isPresent(); + assertThat(foundToken.get().getMember()).isEqualTo(member); + } + + @DisplayName("refreshToken으로 token이 존재하는지 확인한다.") + + @Test + void refreshToken으로_token이_존재하는지_확인한다() { + // given + when(tokenRepository.existsByRefreshToken(anyString())).thenReturn(true); + + // when + boolean exists = tokenRepository.existsByRefreshToken("refresh-token"); + + // then + assertThat(exists).isTrue(); + } + + @DisplayName("refreshToken으로 token을 찾는다.") + + @Test + void refreshToken으로_token을_찾는다() { + // given + when(tokenRepository.findByRefreshToken(anyString())).thenReturn(Optional.of(token)); + + // when + Optional foundToken = tokenRepository.findByRefreshToken("refresh-token"); + + // then + assertThat(foundToken).isPresent(); + assertThat(foundToken.get().getRefreshToken()).isEqualTo("refresh-token"); + } +} diff --git a/src/test/java/shop/kkeujeok/kkeujeokbackend/member/domain/repository/MemberRepositoryTest.java b/src/test/java/shop/kkeujeok/kkeujeokbackend/member/domain/repository/MemberRepositoryTest.java index 988666e0..6411457e 100644 --- a/src/test/java/shop/kkeujeok/kkeujeokbackend/member/domain/repository/MemberRepositoryTest.java +++ b/src/test/java/shop/kkeujeok/kkeujeokbackend/member/domain/repository/MemberRepositoryTest.java @@ -1,5 +1,6 @@ package shop.kkeujeok.kkeujeokbackend.member.domain.repository; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; @@ -19,8 +20,9 @@ class MemberRepositoryTest { @Mock private MemberRepository memberRepository; + @DisplayName("email로 member를 찾는다.") @Test - void testFindByEmail() { + void email로_member를_찾는다() { // given String email = "test@example.com"; Member member = Member.builder() From f848be80816b2ec479b654a77b4b8c92ef305c80 Mon Sep 17 00:00:00 2001 From: inhooo00 Date: Sun, 14 Jul 2024 01:43:44 +0900 Subject: [PATCH 13/16] =?UTF-8?q?Feat(#20):=20AuthServiceFactory=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/AuthServiceFactoryTest.java | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 src/test/java/shop/kkeujeok/kkeujeokbackend/auth/application/AuthServiceFactoryTest.java diff --git a/src/test/java/shop/kkeujeok/kkeujeokbackend/auth/application/AuthServiceFactoryTest.java b/src/test/java/shop/kkeujeok/kkeujeokbackend/auth/application/AuthServiceFactoryTest.java new file mode 100644 index 00000000..5e2768d1 --- /dev/null +++ b/src/test/java/shop/kkeujeok/kkeujeokbackend/auth/application/AuthServiceFactoryTest.java @@ -0,0 +1,45 @@ +package shop.kkeujeok.kkeujeokbackend.auth.application; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.Arrays; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class AuthServiceFactoryTest { + + @Mock + private AuthService authService1; + + @Mock + private AuthService authService2; + + private AuthServiceFactory authServiceFactory; + + @BeforeEach + void setUp() { + when(authService1.getProvider()).thenReturn("provider1"); + when(authService2.getProvider()).thenReturn("provider2"); + + List authServiceList = Arrays.asList(authService1, authService2); + authServiceFactory = new AuthServiceFactory(authServiceList); + } + + @DisplayName("특정 provider에 맞는 AuthService를 반환한다") + @Test + void 특정_provider에_맞는_AuthService를_반환한다() { + AuthService result = authServiceFactory.getAuthService("provider1"); + assertThat(result).isEqualTo(authService1); + + result = authServiceFactory.getAuthService("provider2"); + assertThat(result).isEqualTo(authService2); + } +} From c076f724a98f014f1da0b1cbb911fa268b4fbb45 Mon Sep 17 00:00:00 2001 From: inhooo00 Date: Sun, 14 Jul 2024 21:03:27 +0900 Subject: [PATCH 14/16] =?UTF-8?q?Feat(#20):=20AuthMemberService=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/api/AuthControllerTest.java | 4 + .../application/AuthMemberServiceTest.java | 86 +++++++++++++++++++ .../global/oauth/KakaoAuthServiceTest.java | 4 + 3 files changed, 94 insertions(+) create mode 100644 src/test/java/shop/kkeujeok/kkeujeokbackend/auth/api/AuthControllerTest.java create mode 100644 src/test/java/shop/kkeujeok/kkeujeokbackend/auth/application/AuthMemberServiceTest.java create mode 100644 src/test/java/shop/kkeujeok/kkeujeokbackend/global/oauth/KakaoAuthServiceTest.java diff --git a/src/test/java/shop/kkeujeok/kkeujeokbackend/auth/api/AuthControllerTest.java b/src/test/java/shop/kkeujeok/kkeujeokbackend/auth/api/AuthControllerTest.java new file mode 100644 index 00000000..f727070c --- /dev/null +++ b/src/test/java/shop/kkeujeok/kkeujeokbackend/auth/api/AuthControllerTest.java @@ -0,0 +1,4 @@ +package shop.kkeujeok.kkeujeokbackend.auth.api; + +public class AuthControllerTest { +} diff --git a/src/test/java/shop/kkeujeok/kkeujeokbackend/auth/application/AuthMemberServiceTest.java b/src/test/java/shop/kkeujeok/kkeujeokbackend/auth/application/AuthMemberServiceTest.java new file mode 100644 index 00000000..763a2fb4 --- /dev/null +++ b/src/test/java/shop/kkeujeok/kkeujeokbackend/auth/application/AuthMemberServiceTest.java @@ -0,0 +1,86 @@ +package shop.kkeujeok.kkeujeokbackend.auth.application; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import shop.kkeujeok.kkeujeokbackend.auth.api.dto.response.MemberLoginResDto; +import shop.kkeujeok.kkeujeokbackend.auth.api.dto.response.UserInfo; +import shop.kkeujeok.kkeujeokbackend.global.entity.Status; +import shop.kkeujeok.kkeujeokbackend.member.domain.Member; +import shop.kkeujeok.kkeujeokbackend.member.domain.Role; +import shop.kkeujeok.kkeujeokbackend.member.domain.SocialType; +import shop.kkeujeok.kkeujeokbackend.member.domain.repository.MemberRepository; + +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class AuthMemberServiceTest { + + @Mock + private MemberRepository memberRepository; + + @InjectMocks + private AuthMemberService authMemberService; + + private UserInfo userInfo; + private SocialType provider; + private Member member; + + @BeforeEach + void setUp() { + userInfo = new UserInfo("이메일", "이름", "사진", "닉네임"); + provider = SocialType.GOOGLE; + member = Member.builder() + .status(Status.A) + .email(userInfo.email()) + .name(userInfo.name()) + .picture(userInfo.picture()) + .socialType(provider) + .role(Role.ROLE_USER) + .firstLogin(true) + .nickname(userInfo.nickname()) + .build(); + } + + @DisplayName("신규 회원을 저장합니다.") + @Test + void 신규_회원을_저장합니다() { + when(memberRepository.findByEmail(anyString())).thenReturn(Optional.empty()); + when(memberRepository.save(any(Member.class))).thenReturn(member); + + MemberLoginResDto result = authMemberService.saveUserInfo(userInfo, provider); + + assertThat(result).isNotNull(); + verify(memberRepository).findByEmail(userInfo.email()); + verify(memberRepository).save(any(Member.class)); + } + + @DisplayName("소셜 타입이 일치하지 않는 경우 예외를 던집니다.") + @Test + void 소셜_타입이_일치하지_않는_경우_예외를_던집니다() { + when(memberRepository.findByEmail(anyString())).thenReturn(Optional.of(member)); + SocialType invalidProvider = SocialType.KAKAO; + + assertThrows(RuntimeException.class, () -> authMemberService.saveUserInfo(userInfo, invalidProvider)); + + verify(memberRepository).findByEmail(userInfo.email()); + } + + @Test + @DisplayName("이메일이 null인 경우 테스트") + void testNullEmail() { + UserInfo invalidUserInfo = new UserInfo(null, "Test User", "testUser", "testPicture"); + + assertThrows(RuntimeException.class, () -> authMemberService.saveUserInfo(invalidUserInfo, provider)); + } +} diff --git a/src/test/java/shop/kkeujeok/kkeujeokbackend/global/oauth/KakaoAuthServiceTest.java b/src/test/java/shop/kkeujeok/kkeujeokbackend/global/oauth/KakaoAuthServiceTest.java new file mode 100644 index 00000000..dca0176b --- /dev/null +++ b/src/test/java/shop/kkeujeok/kkeujeokbackend/global/oauth/KakaoAuthServiceTest.java @@ -0,0 +1,4 @@ +package shop.kkeujeok.kkeujeokbackend.global.oauth; + +public class KakaoAuthServiceTest { +} From 4088dea938768977caf302a01ddac76ed5e174ea Mon Sep 17 00:00:00 2001 From: inhooo00 Date: Sun, 14 Jul 2024 21:17:18 +0900 Subject: [PATCH 15/16] =?UTF-8?q?Feat(#20):=20AuthMemberService=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/AuthMemberServiceTest.java | 45 +++++++++++++++++-- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/src/test/java/shop/kkeujeok/kkeujeokbackend/auth/application/AuthMemberServiceTest.java b/src/test/java/shop/kkeujeok/kkeujeokbackend/auth/application/AuthMemberServiceTest.java index 763a2fb4..6f70f32e 100644 --- a/src/test/java/shop/kkeujeok/kkeujeokbackend/auth/application/AuthMemberServiceTest.java +++ b/src/test/java/shop/kkeujeok/kkeujeokbackend/auth/application/AuthMemberServiceTest.java @@ -65,6 +65,21 @@ void setUp() { verify(memberRepository).save(any(Member.class)); } + @DisplayName("회원 정보가 올바르게 저장되는지 확인합니다.") + @Test + void 회원_정보가_올바르게_저장되는지_확인합니다() { + when(memberRepository.findByEmail(anyString())).thenReturn(Optional.empty()); + when(memberRepository.save(any(Member.class))).thenAnswer(invocation -> invocation.getArgument(0)); + + MemberLoginResDto result = authMemberService.saveUserInfo(userInfo, provider); + + assertThat(result).isNotNull(); + assertThat(result.findMember().getEmail()).isEqualTo(userInfo.email()); + assertThat(result.findMember().getName()).isEqualTo(userInfo.name()); + verify(memberRepository).findByEmail(userInfo.email()); + verify(memberRepository).save(any(Member.class)); + } + @DisplayName("소셜 타입이 일치하지 않는 경우 예외를 던집니다.") @Test void 소셜_타입이_일치하지_않는_경우_예외를_던집니다() { @@ -76,11 +91,35 @@ void setUp() { verify(memberRepository).findByEmail(userInfo.email()); } + @DisplayName("이메일이 null인 경우 예외를 던진다.") @Test - @DisplayName("이메일이 null인 경우 테스트") - void testNullEmail() { - UserInfo invalidUserInfo = new UserInfo(null, "Test User", "testUser", "testPicture"); + void 이메일이_null인_경우_예외를_던진다() { + UserInfo invalidUserInfo = new UserInfo(null, "이름", "사진", "닉네임"); assertThrows(RuntimeException.class, () -> authMemberService.saveUserInfo(invalidUserInfo, provider)); } + + @DisplayName("이름이 null인 경우 예외를 던진다.") + @Test + void 이름이_null인_경우_예외를_던진다() { + UserInfo userInfoWithNullName = new UserInfo("이메일", null, "사진", "닉네임"); + + assertThrows(RuntimeException.class, () -> authMemberService.saveUserInfo(userInfoWithNullName, provider)); + } + + @DisplayName("사진이 null인 경우 예외를 던진다.") + @Test + void 사진이_null인_경우_예외를_던진다() { + UserInfo userInfoWithNullPicture = new UserInfo("이메일", "이름", null, "닉네임"); + + assertThrows(RuntimeException.class, () -> authMemberService.saveUserInfo(userInfoWithNullPicture, provider)); + } + + @DisplayName("닉네임이 null인 경우 예외를 던진다.") + @Test + void 닉네임이_null인_경우_예외를_던진다() { + UserInfo userInfoWithNullNickname = new UserInfo("이메일", "이름", "사진", null); + + assertThrows(RuntimeException.class, () -> authMemberService.saveUserInfo(userInfoWithNullNickname, provider)); + } } From 3b0d7d316042c37dfbefb890faf89e15980f02ec Mon Sep 17 00:00:00 2001 From: inhooo00 Date: Sun, 14 Jul 2024 21:43:35 +0900 Subject: [PATCH 16/16] =?UTF-8?q?Refactor(#20):=20display=20=EB=82=B4?= =?UTF-8?q?=EC=9A=A9=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/AuthMemberServiceTest.java | 16 +++++++-------- .../application/AuthServiceFactoryTest.java | 4 ++-- .../auth/application/TokenServiceTest.java | 4 ++-- .../global/jwt/TokenProviderTest.java | 20 +++++++++---------- .../repository/MemberRepositoryTest.java | 4 ++-- 5 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/test/java/shop/kkeujeok/kkeujeokbackend/auth/application/AuthMemberServiceTest.java b/src/test/java/shop/kkeujeok/kkeujeokbackend/auth/application/AuthMemberServiceTest.java index 6f70f32e..e454378f 100644 --- a/src/test/java/shop/kkeujeok/kkeujeokbackend/auth/application/AuthMemberServiceTest.java +++ b/src/test/java/shop/kkeujeok/kkeujeokbackend/auth/application/AuthMemberServiceTest.java @@ -91,33 +91,33 @@ void setUp() { verify(memberRepository).findByEmail(userInfo.email()); } - @DisplayName("이메일이 null인 경우 예외를 던진다.") + @DisplayName("이메일이 null인 경우 예외를 던집니다.") @Test - void 이메일이_null인_경우_예외를_던진다() { + void 이메일이_null인_경우_예외를_던집니다() { UserInfo invalidUserInfo = new UserInfo(null, "이름", "사진", "닉네임"); assertThrows(RuntimeException.class, () -> authMemberService.saveUserInfo(invalidUserInfo, provider)); } - @DisplayName("이름이 null인 경우 예외를 던진다.") + @DisplayName("이름이 null인 경우 예외를 던집니다.") @Test - void 이름이_null인_경우_예외를_던진다() { + void 이름이_null인_경우_예외를_던집니다() { UserInfo userInfoWithNullName = new UserInfo("이메일", null, "사진", "닉네임"); assertThrows(RuntimeException.class, () -> authMemberService.saveUserInfo(userInfoWithNullName, provider)); } - @DisplayName("사진이 null인 경우 예외를 던진다.") + @DisplayName("사진이 null인 경우 예외를 던집니다.") @Test - void 사진이_null인_경우_예외를_던진다() { + void 사진이_null인_경우_예외를_던집니다() { UserInfo userInfoWithNullPicture = new UserInfo("이메일", "이름", null, "닉네임"); assertThrows(RuntimeException.class, () -> authMemberService.saveUserInfo(userInfoWithNullPicture, provider)); } - @DisplayName("닉네임이 null인 경우 예외를 던진다.") + @DisplayName("닉네임이 null인 경우 예외를 던집니다.") @Test - void 닉네임이_null인_경우_예외를_던진다() { + void 닉네임이_null인_경우_예외를_던집니다() { UserInfo userInfoWithNullNickname = new UserInfo("이메일", "이름", "사진", null); assertThrows(RuntimeException.class, () -> authMemberService.saveUserInfo(userInfoWithNullNickname, provider)); diff --git a/src/test/java/shop/kkeujeok/kkeujeokbackend/auth/application/AuthServiceFactoryTest.java b/src/test/java/shop/kkeujeok/kkeujeokbackend/auth/application/AuthServiceFactoryTest.java index 5e2768d1..bebffe70 100644 --- a/src/test/java/shop/kkeujeok/kkeujeokbackend/auth/application/AuthServiceFactoryTest.java +++ b/src/test/java/shop/kkeujeok/kkeujeokbackend/auth/application/AuthServiceFactoryTest.java @@ -33,9 +33,9 @@ void setUp() { authServiceFactory = new AuthServiceFactory(authServiceList); } - @DisplayName("특정 provider에 맞는 AuthService를 반환한다") + @DisplayName("특정 provider에 맞는 AuthService를 반환합니다") @Test - void 특정_provider에_맞는_AuthService를_반환한다() { + void 특정_provider에_맞는_AuthService를_반환합니다() { AuthService result = authServiceFactory.getAuthService("provider1"); assertThat(result).isEqualTo(authService1); diff --git a/src/test/java/shop/kkeujeok/kkeujeokbackend/auth/application/TokenServiceTest.java b/src/test/java/shop/kkeujeok/kkeujeokbackend/auth/application/TokenServiceTest.java index 28a937fa..85e1986d 100644 --- a/src/test/java/shop/kkeujeok/kkeujeokbackend/auth/application/TokenServiceTest.java +++ b/src/test/java/shop/kkeujeok/kkeujeokbackend/auth/application/TokenServiceTest.java @@ -58,9 +58,9 @@ void setUp() { when(tokenDto.refreshToken()).thenReturn("new-refresh-token"); } - @DisplayName("accessToken과 refreshToken을 생성한다.") + @DisplayName("accessToken과 refreshToken을 생성합니다.") @Test - void accessToken과_refreshToken을_생성한다() { + void accessToken과_refreshToken을_생성합니다() { when(tokenRepository.existsByMember(any(Member.class))).thenReturn(false); TokenDto result = tokenService.getToken(memberLoginResDto); diff --git a/src/test/java/shop/kkeujeok/kkeujeokbackend/global/jwt/TokenProviderTest.java b/src/test/java/shop/kkeujeok/kkeujeokbackend/global/jwt/TokenProviderTest.java index 9830848c..763c26b1 100644 --- a/src/test/java/shop/kkeujeok/kkeujeokbackend/global/jwt/TokenProviderTest.java +++ b/src/test/java/shop/kkeujeok/kkeujeokbackend/global/jwt/TokenProviderTest.java @@ -24,9 +24,9 @@ void init() { tokenProvider.init(); } - @DisplayName("엑세스 토큰을 생성한다.") + @DisplayName("엑세스 토큰을 생성합니다.") @Test - void 엑세스_토큰을_생성한다() { + void 엑세스_토큰을_생성합니다() { // given String email = "inho@gmail.com"; @@ -38,9 +38,9 @@ void init() { assertThat(actual.split("\\.")).hasSize(3); } - @DisplayName("리프레시 토큰을 생성한다.") + @DisplayName("리프레시 토큰을 생성합니다.") @Test - void 리프레시_토큰을_생성한다() { + void 리프레시_토큰을_생성합니다() { // given, when String actual = tokenProvider.generateRefreshToken(); @@ -50,9 +50,9 @@ void init() { assertThat(actual.split("\\.")).hasSize(3); } - @DisplayName("토큰들을 반환한다.") + @DisplayName("토큰들을 반환합니다.") @Test - void 토큰들을_반환한다() { + void 토큰들을_반환합니다() { // given String email = "inho@gmail.com"; @@ -63,9 +63,9 @@ void init() { assertThat(actual).isNotNull(); // 토큰이 null이 아닌지 확인 } - @DisplayName("리프레시 토큰으로 엑세스 토큰을 반환한다.") + @DisplayName("리프레시 토큰으로 엑세스 토큰을 반환합니다.") @Test - void 리프레시_토큰으로_엑세스_토큰을_반환한다() { + void 리프레시_토큰으로_엑세스_토큰을_반환합니다() { // given String refreshToken = "refreshToken"; String email = "inho@gmail.com"; @@ -77,9 +77,9 @@ void init() { assertThat(actual).isNotNull(); } - @DisplayName("토큰을 검증하여 유효하지 않으면 false를 반환한다.") + @DisplayName("토큰을 검증하여 유효하지 않으면 false를 반환합니다.") @Test - void 토큰을_검증하여_유효하지_않으면_false를_반환한다() { + void 토큰을_검증하여_유효하지_않으면_false를_반환합니다() { // given String malformedToken = "malformedToken"; diff --git a/src/test/java/shop/kkeujeok/kkeujeokbackend/member/domain/repository/MemberRepositoryTest.java b/src/test/java/shop/kkeujeok/kkeujeokbackend/member/domain/repository/MemberRepositoryTest.java index 6411457e..65d46b62 100644 --- a/src/test/java/shop/kkeujeok/kkeujeokbackend/member/domain/repository/MemberRepositoryTest.java +++ b/src/test/java/shop/kkeujeok/kkeujeokbackend/member/domain/repository/MemberRepositoryTest.java @@ -20,9 +20,9 @@ class MemberRepositoryTest { @Mock private MemberRepository memberRepository; - @DisplayName("email로 member를 찾는다.") + @DisplayName("email로 member를 찾습니다.") @Test - void email로_member를_찾는다() { + void email로_member를_찾습니다() { // given String email = "test@example.com"; Member member = Member.builder()