From de3b0eeccf3dd99c98fdbd94e88b5adf45585e47 Mon Sep 17 00:00:00 2001 From: "Choi, Minwoo" Date: Thu, 14 Aug 2025 21:29:21 +0900 Subject: [PATCH] =?UTF-8?q?refactor:=20=EC=B9=B4=EC=B9=B4=EC=98=A4=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EB=A9=A4=EB=B2=84=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EB=A1=9C=EC=A7=81=20=EA=B0=9C=EC=84=A0(#54)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: MemberService.getMemberBySocialProviderAndSocialId()에 MemberPolicy.validateNotDeleted() 추가 * test: MemberServiceTest에 탈퇴 회원 예외 발생 테스트 추가 * test: AuthControllerIntegrationTest에 탈퇴 회원 예외 발생 통합 테스트 추가 * test: KakaoOauthTestHelper 추가 --- .../controller/AuthController.java | 4 ++ .../application/service/MemberService.java | 11 +++- .../auth/helper/KakaoOauthTestHelper.java | 35 ++++++++++++ .../auth/helper/TokenTestHelper.java | 1 - .../AuthControllerIntegrationTest.java | 55 ++++++++++++------- .../service/MemberServiceTest.java | 17 ++++++ 6 files changed, 100 insertions(+), 23 deletions(-) create mode 100644 src/test/java/com/ject/studytrip/auth/helper/KakaoOauthTestHelper.java diff --git a/src/main/java/com/ject/studytrip/auth/presentation/controller/AuthController.java b/src/main/java/com/ject/studytrip/auth/presentation/controller/AuthController.java index 99e3223..0d1eaf5 100644 --- a/src/main/java/com/ject/studytrip/auth/presentation/controller/AuthController.java +++ b/src/main/java/com/ject/studytrip/auth/presentation/controller/AuthController.java @@ -30,6 +30,7 @@ public class AuthController { public ResponseEntity kakaoLogin( @Valid @RequestBody KakaoLoginRequest request) { TokenResponse response = authFacade.kakaoLogin(request); + return ResponseEntity.ok(StandardResponse.success(HttpStatus.OK.value(), response)); } @@ -40,6 +41,7 @@ public ResponseEntity kakaoLogin( public ResponseEntity kakaoSignup( @Valid @RequestBody KakaoSignupRequest request) { TokenResponse response = authFacade.kakaoSignup(request); + return ResponseEntity.ok(StandardResponse.success(HttpStatus.OK.value(), response)); } @@ -48,6 +50,7 @@ public ResponseEntity kakaoSignup( public ResponseEntity reissueToken( @Valid @RequestBody TokenReissueRequest request) { TokenResponse response = authFacade.reissueToken(request); + return ResponseEntity.ok(StandardResponse.success(HttpStatus.OK.value(), response)); } @@ -57,6 +60,7 @@ public ResponseEntity reissueToken( @PostMapping("/logout") public ResponseEntity logout(@Valid @RequestBody LogoutRequest request) { authFacade.logout(request); + return ResponseEntity.ok(StandardResponse.success(HttpStatus.OK.value(), null)); } } diff --git a/src/main/java/com/ject/studytrip/member/application/service/MemberService.java b/src/main/java/com/ject/studytrip/member/application/service/MemberService.java index 07085a6..1257582 100644 --- a/src/main/java/com/ject/studytrip/member/application/service/MemberService.java +++ b/src/main/java/com/ject/studytrip/member/application/service/MemberService.java @@ -62,9 +62,14 @@ public Member getMember(Long memberId) { @Transactional(readOnly = true) public Member getMemberBySocialProviderAndSocialId( SocialProvider socialProvider, String socialId) { - return memberRepository - .findBySocialProviderAndSocialId(socialProvider, socialId) - .orElseThrow(() -> new CustomException(MemberErrorCode.MEMBER_NEED_SIGNUP)); + Member member = + memberRepository + .findBySocialProviderAndSocialId(socialProvider, socialId) + .orElseThrow(() -> new CustomException(MemberErrorCode.MEMBER_NEED_SIGNUP)); + + MemberPolicy.validateNotDeleted(member); + + return member; } @Transactional(readOnly = true) diff --git a/src/test/java/com/ject/studytrip/auth/helper/KakaoOauthTestHelper.java b/src/test/java/com/ject/studytrip/auth/helper/KakaoOauthTestHelper.java new file mode 100644 index 0000000..306b8c1 --- /dev/null +++ b/src/test/java/com/ject/studytrip/auth/helper/KakaoOauthTestHelper.java @@ -0,0 +1,35 @@ +package com.ject.studytrip.auth.helper; + +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.BDDMockito.given; + +import com.ject.studytrip.auth.infra.dto.KakaoTokenResponse; +import com.ject.studytrip.auth.infra.dto.KakaoUserInfoResponse; +import com.ject.studytrip.auth.infra.provider.KakaoOauthProvider; +import com.ject.studytrip.global.exception.CustomException; +import com.ject.studytrip.member.domain.error.MemberErrorCode; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class KakaoOauthTestHelper { + private final KakaoOauthProvider kakaoOauthProvider; + + @Autowired + public KakaoOauthTestHelper(KakaoOauthProvider kakaoOauthProvider) { + this.kakaoOauthProvider = kakaoOauthProvider; + } + + public void mockSuccess( + KakaoTokenResponse kakaoTokenResponse, KakaoUserInfoResponse kakaoUserInfoResponse) { + given(kakaoOauthProvider.getKakaoTokens(anyString())).willReturn(kakaoTokenResponse); + given(kakaoOauthProvider.getKakaoUserInfo(anyString())).willReturn(kakaoUserInfoResponse); + } + + public void mockThrowException( + KakaoTokenResponse kakaoTokenResponse, MemberErrorCode memberErrorCode) { + given(kakaoOauthProvider.getKakaoTokens(anyString())).willReturn(kakaoTokenResponse); + given(kakaoOauthProvider.getKakaoUserInfo(anyString())) + .willThrow(new CustomException(memberErrorCode)); + } +} diff --git a/src/test/java/com/ject/studytrip/auth/helper/TokenTestHelper.java b/src/test/java/com/ject/studytrip/auth/helper/TokenTestHelper.java index 0e372c4..cdba0de 100644 --- a/src/test/java/com/ject/studytrip/auth/helper/TokenTestHelper.java +++ b/src/test/java/com/ject/studytrip/auth/helper/TokenTestHelper.java @@ -6,7 +6,6 @@ @Component public class TokenTestHelper { - private final TokenProvider tokenProvider; @Autowired diff --git a/src/test/java/com/ject/studytrip/auth/presentation/controller/AuthControllerIntegrationTest.java b/src/test/java/com/ject/studytrip/auth/presentation/controller/AuthControllerIntegrationTest.java index 627b98f..64a8965 100644 --- a/src/test/java/com/ject/studytrip/auth/presentation/controller/AuthControllerIntegrationTest.java +++ b/src/test/java/com/ject/studytrip/auth/presentation/controller/AuthControllerIntegrationTest.java @@ -1,7 +1,5 @@ package com.ject.studytrip.auth.presentation.controller; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.BDDMockito.given; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; @@ -10,6 +8,7 @@ import com.ject.studytrip.auth.domain.repository.RefreshTokenRedisRepository; import com.ject.studytrip.auth.fixture.*; import com.ject.studytrip.auth.fixture.TokenReissueRequestFixture; +import com.ject.studytrip.auth.helper.KakaoOauthTestHelper; import com.ject.studytrip.auth.helper.TokenTestHelper; import com.ject.studytrip.auth.infra.dto.KakaoTokenResponse; import com.ject.studytrip.auth.infra.dto.KakaoUserInfoResponse; @@ -18,7 +17,6 @@ import com.ject.studytrip.auth.presentation.dto.request.KakaoSignupRequest; import com.ject.studytrip.auth.presentation.dto.request.LogoutRequest; import com.ject.studytrip.auth.presentation.dto.request.TokenReissueRequest; -import com.ject.studytrip.global.exception.CustomException; import com.ject.studytrip.global.exception.error.CommonErrorCode; import com.ject.studytrip.member.domain.error.MemberErrorCode; import com.ject.studytrip.member.domain.model.Member; @@ -40,6 +38,7 @@ class AuthControllerIntegrationTest extends BaseIntegrationTest { @Autowired private MemberTestHelper memberTestHelper; @Autowired private TokenTestHelper tokenTestHelper; + @Autowired private KakaoOauthTestHelper kakaoOauthTestHelper; @Autowired private RefreshTokenRedisRepository refreshTokenRedisRepository; @MockitoBean KakaoOauthProvider kakaoOauthProvider; @@ -55,6 +54,7 @@ void setUp() { tokenTestHelper.createAccessToken( member.getId().toString(), member.getRole().name()); refreshToken = tokenTestHelper.createRefreshToken(); + long refreshTokenExpirationTime = Duration.ofSeconds(30).getSeconds(); refreshTokenRedisRepository.saveRefreshToken( member.getId().toString(), refreshToken, refreshTokenExpirationTime); @@ -84,10 +84,8 @@ void shouldReturnConflictWhenMemberNotSignUp() throws Exception { member.updateDeletedAt(); KakaoLoginRequest request = kakaoLoginRequestFixture.build(); KakaoTokenResponse kakaoTokenResponse = kakaoTokenResponseFixture.build(); - - given(kakaoOauthProvider.getKakaoTokens(anyString())).willReturn(kakaoTokenResponse); - given(kakaoOauthProvider.getKakaoUserInfo(anyString())) - .willThrow(new CustomException(MemberErrorCode.MEMBER_NEED_SIGNUP)); + kakaoOauthTestHelper.mockThrowException( + kakaoTokenResponse, MemberErrorCode.MEMBER_NEED_SIGNUP); // when ResultActions resultActions = getResultActions(request); @@ -107,6 +105,34 @@ void shouldReturnConflictWhenMemberNotSignUp() throws Exception { .value(MemberErrorCode.MEMBER_NEED_SIGNUP.getMessage())); } + @Test + @DisplayName("탈퇴한 사용자가 인가 코드로 로그인 시 400 Bad Request를 반환한다.") + void shouldReturnBadRequestWhenMemberAlreadyDeleted() throws Exception { + // given + member.updateDeletedAt(); + KakaoLoginRequest request = kakaoLoginRequestFixture.build(); + KakaoTokenResponse kakaoTokenResponse = kakaoTokenResponseFixture.build(); + kakaoOauthTestHelper.mockThrowException( + kakaoTokenResponse, MemberErrorCode.MEMBER_ALREADY_DELETED); + + // when + ResultActions resultActions = getResultActions(request); + + // then + resultActions + .andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.success").value(false)) + .andExpect( + jsonPath("$.status") + .value( + MemberErrorCode.MEMBER_ALREADY_DELETED + .getStatus() + .value())) + .andExpect( + jsonPath("$.data.message") + .value(MemberErrorCode.MEMBER_ALREADY_DELETED.getMessage())); + } + @Test @DisplayName("가입된 사용자의 인가 코드로 로그인하면 토큰이 발급된다.") void shouldReturnTokenResponseWhenLoginIsSuccessful() throws Exception { @@ -114,10 +140,7 @@ void shouldReturnTokenResponseWhenLoginIsSuccessful() throws Exception { KakaoLoginRequest request = kakaoLoginRequestFixture.build(); KakaoTokenResponse kakaoTokenResponse = kakaoTokenResponseFixture.build(); KakaoUserInfoResponse kakaoUserInfoResponse = kakaoUserInfoResponseFixture.build(); - - given(kakaoOauthProvider.getKakaoTokens(anyString())).willReturn(kakaoTokenResponse); - given(kakaoOauthProvider.getKakaoUserInfo(anyString())) - .willReturn(kakaoUserInfoResponse); + kakaoOauthTestHelper.mockSuccess(kakaoTokenResponse, kakaoUserInfoResponse); // when ResultActions resultActions = getResultActions(request); @@ -156,10 +179,7 @@ void shouldThrowExceptionWhenSignupForExistingMember() throws Exception { KakaoSignupRequest request = kakaoSignupRequestFixture.build(); KakaoTokenResponse kakaoTokenResponse = kakaoTokenResponseFixture.build(); KakaoUserInfoResponse kakaoUserInfoResponse = kakaoUserInfoResponseFixture.build(); - - given(kakaoOauthProvider.getKakaoTokens(anyString())).willReturn(kakaoTokenResponse); - given(kakaoOauthProvider.getKakaoUserInfo(anyString())) - .willReturn(kakaoUserInfoResponse); + kakaoOauthTestHelper.mockSuccess(kakaoTokenResponse, kakaoUserInfoResponse); // when ResultActions resultActions = getResultActions(request); @@ -187,10 +207,7 @@ void shouldReturnTokenResponseWhenSignupIsSuccessful() throws Exception { KakaoSignupRequest request = kakaoSignupRequestFixture.build(); KakaoTokenResponse kakaoTokenResponse = kakaoTokenResponseFixture.build(); KakaoUserInfoResponse kakaoUserInfoResponse = kakaoUserInfoResponseFixture.build(); - - given(kakaoOauthProvider.getKakaoTokens(anyString())).willReturn(kakaoTokenResponse); - given(kakaoOauthProvider.getKakaoUserInfo(anyString())) - .willReturn(kakaoUserInfoResponse); + kakaoOauthTestHelper.mockSuccess(kakaoTokenResponse, kakaoUserInfoResponse); // when ResultActions resultActions = getResultActions(request); diff --git a/src/test/java/com/ject/studytrip/member/application/service/MemberServiceTest.java b/src/test/java/com/ject/studytrip/member/application/service/MemberServiceTest.java index 57c4ba8..87d8851 100644 --- a/src/test/java/com/ject/studytrip/member/application/service/MemberServiceTest.java +++ b/src/test/java/com/ject/studytrip/member/application/service/MemberServiceTest.java @@ -265,6 +265,23 @@ void shouldThrowExceptionWhenSocialIdNotFound() { .hasMessage(MemberErrorCode.MEMBER_NEED_SIGNUP.getMessage()); } + @Test + @DisplayName("탈퇴한 Member라면 예외가 발생한다.") + void shouldThrowExceptionWhenMemberAlreadyDeleted() { + // given + member.updateDeletedAt(); + given(memberRepository.findBySocialProviderAndSocialId(SocialProvider.KAKAO, socialId)) + .willReturn(Optional.of(member)); + + // when & then + assertThatThrownBy( + () -> + memberService.getMemberBySocialProviderAndSocialId( + SocialProvider.KAKAO, socialId)) + .isInstanceOf(CustomException.class) + .hasMessage(MemberErrorCode.MEMBER_ALREADY_DELETED.getMessage()); + } + @Test @DisplayName("소셜 ID로 조회 시 존재하면 Member를 반환한다.") void shouldReturnMemberWhenSocialIdExists() {