diff --git a/src/main/java/com/prgrms/nabmart/domain/order/controller/OrderController.java b/src/main/java/com/prgrms/nabmart/domain/order/controller/OrderController.java index 6759bafb2..d07c707c2 100644 --- a/src/main/java/com/prgrms/nabmart/domain/order/controller/OrderController.java +++ b/src/main/java/com/prgrms/nabmart/domain/order/controller/OrderController.java @@ -22,6 +22,7 @@ import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @@ -88,7 +89,7 @@ public ResponseEntity deleteOrder( @GetMapping("/payed") public ResponseEntity findPayedOrders( - @RequestBody @Valid FindPayedOrdersRequest findPayedOrdersRequest, + @ModelAttribute @Valid FindPayedOrdersRequest findPayedOrdersRequest, @LoginUser Long userId) { FindPayedOrdersCommand command = FindPayedOrdersCommand.of( userId, diff --git a/src/main/java/com/prgrms/nabmart/global/auth/oauth/client/OAuthRestClient.java b/src/main/java/com/prgrms/nabmart/global/auth/oauth/client/OAuthRestClient.java index 7a159b965..dbe111788 100644 --- a/src/main/java/com/prgrms/nabmart/global/auth/oauth/client/OAuthRestClient.java +++ b/src/main/java/com/prgrms/nabmart/global/auth/oauth/client/OAuthRestClient.java @@ -1,10 +1,100 @@ package com.prgrms.nabmart.global.auth.oauth.client; import com.prgrms.nabmart.domain.user.service.response.FindUserDetailResponse; +import com.prgrms.nabmart.global.auth.oauth.OAuthProvider; +import com.prgrms.nabmart.global.auth.oauth.dto.OAuthHttpMessage; +import com.prgrms.nabmart.global.infrastructure.ApiService; +import java.time.Instant; +import java.util.List; +import java.util.Map; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService; +import org.springframework.security.oauth2.core.OAuth2AccessToken; +import org.springframework.security.oauth2.core.OAuth2RefreshToken; +import org.springframework.stereotype.Component; -public interface OAuthRestClient { +@Slf4j +@Component +@RequiredArgsConstructor +public class OAuthRestClient { - void callUnlinkOAuthUser(FindUserDetailResponse userDetailResponse); + private final ApiService apiService; + private final OAuth2AuthorizedClientService authorizedClientService; - void callRefreshAccessToken(FindUserDetailResponse userDetailResponse); + public void callUnlinkOAuthUser(final FindUserDetailResponse userDetailResponse) { + OAuthProvider oAuthProvider = OAuthProvider.getOAuthProvider(userDetailResponse.provider()); + OAuthHttpMessageProvider oAuthHttpMessageProvider = oAuthProvider.getOAuthHttpMessageProvider(); + OAuth2AuthorizedClient oAuth2AuthorizedClient = authorizedClientService.loadAuthorizedClient( + userDetailResponse.provider(), + userDetailResponse.providerId()); + + refreshAccessTokenIfNotValid(userDetailResponse, oAuth2AuthorizedClient); + + OAuthHttpMessage unlinkHttpMessage = oAuthHttpMessageProvider.createUnlinkUserRequest( + userDetailResponse, oAuth2AuthorizedClient); + + Map response = sendPostApiRequest(unlinkHttpMessage); + log.info("회원의 연결이 종료되었습니다. 회원 ID={}", response); + + oAuthHttpMessageProvider.verifySuccessUnlinkUserRequest(response); + authorizedClientService.removeAuthorizedClient( + userDetailResponse.provider(), + userDetailResponse.provider()); + } + + private void refreshAccessTokenIfNotValid(FindUserDetailResponse userDetailResponse, + OAuth2AuthorizedClient oAuth2AuthorizedClient) { + Instant expiresAt = oAuth2AuthorizedClient.getAccessToken().getExpiresAt(); + if(expiresAt.isBefore(Instant.now())) { + callRefreshAccessToken(userDetailResponse); + } + } + + public void callRefreshAccessToken(final FindUserDetailResponse userDetailResponse) { + OAuthProvider oAuthProvider = OAuthProvider.getOAuthProvider(userDetailResponse.provider()); + OAuthHttpMessageProvider oAuthHttpMessageProvider = oAuthProvider.getOAuthHttpMessageProvider(); + OAuth2AuthorizedClient oAuth2AuthorizedClient = authorizedClientService.loadAuthorizedClient( + userDetailResponse.provider(), + userDetailResponse.providerId()); + OAuthHttpMessage refreshAccessTokenRequest + = oAuthHttpMessageProvider.createRefreshAccessTokenRequest(oAuth2AuthorizedClient); + + Map response = sendPostApiRequest(refreshAccessTokenRequest); + + OAuth2AccessToken refreshedAccessToken + = oAuthHttpMessageProvider.extractAccessToken(response); + OAuth2RefreshToken refreshedRefreshToken + = oAuthHttpMessageProvider.extractRefreshToken(response) + .orElse(oAuth2AuthorizedClient.getRefreshToken()); + + OAuth2AuthorizedClient updatedAuthorizedClient = new OAuth2AuthorizedClient( + oAuth2AuthorizedClient.getClientRegistration(), + oAuth2AuthorizedClient.getPrincipalName(), + refreshedAccessToken, + refreshedRefreshToken); + Authentication authenticationForTokenRefresh + = getAuthenticationForTokenRefresh(updatedAuthorizedClient); + authorizedClientService.saveAuthorizedClient( + updatedAuthorizedClient, + authenticationForTokenRefresh); + } + + private Authentication getAuthenticationForTokenRefresh( + OAuth2AuthorizedClient updatedAuthorizedClient) { + String principalName = updatedAuthorizedClient.getPrincipalName(); + return UsernamePasswordAuthenticationToken.authenticated( + principalName, null, List.of()); + } + + private Map sendPostApiRequest(OAuthHttpMessage request) { + return apiService.getResult( + request.httpMessage(), + request.uri(), + Map.class, + request.uriVariables()); + } } diff --git a/src/main/java/com/prgrms/nabmart/global/auth/oauth/client/RestTemplateOAuthClient.java b/src/main/java/com/prgrms/nabmart/global/auth/oauth/client/RestTemplateOAuthClient.java deleted file mode 100644 index 52c7e9ef3..000000000 --- a/src/main/java/com/prgrms/nabmart/global/auth/oauth/client/RestTemplateOAuthClient.java +++ /dev/null @@ -1,105 +0,0 @@ -package com.prgrms.nabmart.global.auth.oauth.client; - -import com.prgrms.nabmart.domain.user.service.response.FindUserDetailResponse; -import com.prgrms.nabmart.global.auth.oauth.dto.OAuthHttpMessage; -import com.prgrms.nabmart.global.auth.oauth.OAuthProvider; -import java.time.Instant; -import java.util.List; -import java.util.Map; -import lombok.extern.slf4j.Slf4j; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.Authentication; -import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; -import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService; -import org.springframework.security.oauth2.core.OAuth2AccessToken; -import org.springframework.security.oauth2.core.OAuth2RefreshToken; -import org.springframework.stereotype.Component; -import org.springframework.web.client.RestTemplate; - -@Slf4j -@Component -public class RestTemplateOAuthClient implements OAuthRestClient { - - private final RestTemplate restTemplate; - private final OAuth2AuthorizedClientService authorizedClientService; - - public RestTemplateOAuthClient(final OAuth2AuthorizedClientService authorizedClientService) { - this.authorizedClientService = authorizedClientService; - this.restTemplate = new RestTemplate(); - } - - @Override - public void callUnlinkOAuthUser(final FindUserDetailResponse userDetailResponse) { - OAuthProvider oAuthProvider = OAuthProvider.getOAuthProvider(userDetailResponse.provider()); - OAuthHttpMessageProvider oAuthHttpMessageProvider = oAuthProvider.getOAuthHttpMessageProvider(); - OAuth2AuthorizedClient oAuth2AuthorizedClient = authorizedClientService.loadAuthorizedClient( - userDetailResponse.provider(), - userDetailResponse.providerId()); - - refreshAccessTokenIfNotValid(userDetailResponse, oAuth2AuthorizedClient); - - OAuthHttpMessage unlinkHttpMessage = oAuthHttpMessageProvider.createUnlinkUserRequest( - userDetailResponse, oAuth2AuthorizedClient); - - Map response = sendPostApiRequest(unlinkHttpMessage); - log.info("회원의 연결이 종료되었습니다. 회원 ID={}", response); - - oAuthHttpMessageProvider.verifySuccessUnlinkUserRequest(response); - authorizedClientService.removeAuthorizedClient( - userDetailResponse.provider(), - userDetailResponse.provider()); - } - - private void refreshAccessTokenIfNotValid(FindUserDetailResponse userDetailResponse, - OAuth2AuthorizedClient oAuth2AuthorizedClient) { - Instant expiresAt = oAuth2AuthorizedClient.getAccessToken().getExpiresAt(); - if(expiresAt.isBefore(Instant.now())) { - callRefreshAccessToken(userDetailResponse); - } - } - - @Override - public void callRefreshAccessToken(final FindUserDetailResponse userDetailResponse) { - OAuthProvider oAuthProvider = OAuthProvider.getOAuthProvider(userDetailResponse.provider()); - OAuthHttpMessageProvider oAuthHttpMessageProvider = oAuthProvider.getOAuthHttpMessageProvider(); - OAuth2AuthorizedClient oAuth2AuthorizedClient = authorizedClientService.loadAuthorizedClient( - userDetailResponse.provider(), - userDetailResponse.providerId()); - OAuthHttpMessage refreshAccessTokenRequest - = oAuthHttpMessageProvider.createRefreshAccessTokenRequest(oAuth2AuthorizedClient); - - Map response = sendPostApiRequest(refreshAccessTokenRequest); - - OAuth2AccessToken refreshedAccessToken - = oAuthHttpMessageProvider.extractAccessToken(response); - OAuth2RefreshToken refreshedRefreshToken - = oAuthHttpMessageProvider.extractRefreshToken(response) - .orElse(oAuth2AuthorizedClient.getRefreshToken()); - - OAuth2AuthorizedClient updatedAuthorizedClient = new OAuth2AuthorizedClient( - oAuth2AuthorizedClient.getClientRegistration(), - oAuth2AuthorizedClient.getPrincipalName(), - refreshedAccessToken, - refreshedRefreshToken); - Authentication authenticationForTokenRefresh - = getAuthenticationForTokenRefresh(updatedAuthorizedClient); - authorizedClientService.saveAuthorizedClient( - updatedAuthorizedClient, - authenticationForTokenRefresh); - } - - private Authentication getAuthenticationForTokenRefresh( - OAuth2AuthorizedClient updatedAuthorizedClient) { - String principalName = updatedAuthorizedClient.getPrincipalName(); - return UsernamePasswordAuthenticationToken.authenticated( - principalName, null, List.of()); - } - - private Map sendPostApiRequest(OAuthHttpMessage request) { - return restTemplate.postForObject( - request.uri(), - request.httpMessage(), - Map.class, - request.uriVariables()); - } -} diff --git a/src/main/java/com/prgrms/nabmart/global/infrastructure/ApiService.java b/src/main/java/com/prgrms/nabmart/global/infrastructure/ApiService.java index e9f1f407b..a55ff07e1 100644 --- a/src/main/java/com/prgrms/nabmart/global/infrastructure/ApiService.java +++ b/src/main/java/com/prgrms/nabmart/global/infrastructure/ApiService.java @@ -2,6 +2,8 @@ import com.prgrms.nabmart.global.exception.ExternalApiException; import java.time.Duration; +import java.util.Collections; +import java.util.Map; import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.http.HttpEntity; import org.springframework.http.ResponseEntity; @@ -21,7 +23,12 @@ public ApiService(RestTemplateBuilder restTemplateBuilder) { } public T getResult(HttpEntity httpEntity, String url, Class clazz) { - ResponseEntity response = callExternalApi(url, httpEntity, clazz); + return getResult(httpEntity, url, clazz, Collections.emptyMap()); + } + + public T getResult(HttpEntity httpEntity, String url, Class clazz, + Map uriVariables) { + ResponseEntity response = callExternalApi(url, httpEntity, clazz, uriVariables); if (response.getStatusCode().isError()) { throw new ExternalApiException("외부 API 호출 과정에서 오류가 발생했습니다"); } @@ -32,9 +39,10 @@ public T getResult(HttpEntity httpEntity, String url, Class clazz) { private ResponseEntity callExternalApi( String url, HttpEntity httpEntity, - Class clazz) { + Class clazz, + Map uriVariables) { try { - return restTemplate.postForEntity(url, httpEntity, clazz); + return restTemplate.postForEntity(url, httpEntity, clazz, uriVariables); } catch (Exception exception) { throw new ExternalApiException("외부 API 호출 과정에서 오류가 발생했습니다"); } diff --git a/src/test/java/com/prgrms/nabmart/domain/order/controller/OrderControllerTest.java b/src/test/java/com/prgrms/nabmart/domain/order/controller/OrderControllerTest.java index 463846d4a..839d07295 100644 --- a/src/test/java/com/prgrms/nabmart/domain/order/controller/OrderControllerTest.java +++ b/src/test/java/com/prgrms/nabmart/domain/order/controller/OrderControllerTest.java @@ -21,7 +21,6 @@ import static org.springframework.restdocs.payload.JsonFieldType.NUMBER; import static org.springframework.restdocs.payload.JsonFieldType.STRING; import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; -import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; @@ -32,12 +31,11 @@ import com.prgrms.nabmart.domain.coupon.UserCoupon; import com.prgrms.nabmart.domain.order.Order; import com.prgrms.nabmart.domain.order.controller.request.CreateOrderRequest; -import com.prgrms.nabmart.domain.order.controller.request.FindPayedOrdersRequest; -import com.prgrms.nabmart.domain.order.service.response.FindPayedOrdersResponse; -import com.prgrms.nabmart.domain.order.service.response.FindPayedOrdersResponse.FindPayedOrderResponse; import com.prgrms.nabmart.domain.order.service.response.CreateOrderResponse; import com.prgrms.nabmart.domain.order.service.response.FindOrderDetailResponse; import com.prgrms.nabmart.domain.order.service.response.FindOrdersResponse; +import com.prgrms.nabmart.domain.order.service.response.FindPayedOrdersResponse; +import com.prgrms.nabmart.domain.order.service.response.FindPayedOrdersResponse.FindPayedOrderResponse; import com.prgrms.nabmart.domain.order.service.response.UpdateOrderByCouponResponse; import com.prgrms.nabmart.domain.user.User; import java.util.List; @@ -247,7 +245,6 @@ class FindPayedOrdersTest { void findPayedOrders() throws Exception { //given int page = 0; - FindPayedOrdersRequest findPayedOrdersRequest = new FindPayedOrdersRequest(page); FindPayedOrderResponse findPayedOrderResponse = new FindPayedOrderResponse(1L, "비비고 왕교자 외 2개", 20000); FindPayedOrdersResponse findPayedOrdersResponse = new FindPayedOrdersResponse( @@ -258,8 +255,7 @@ void findPayedOrders() throws Exception { //when ResultActions resultActions = mockMvc.perform(get("/api/v1/orders/payed") .header(AUTHORIZATION, accessToken) - .contentType(MediaType.APPLICATION_JSON) - .content(objectMapper.writeValueAsString(findPayedOrdersRequest))); + .param("page", String.valueOf(page))); //then resultActions.andExpect(status().isOk()) @@ -267,8 +263,8 @@ void findPayedOrders() throws Exception { requestHeaders( headerWithName(AUTHORIZATION).description("액세스 토큰") ), - requestFields( - fieldWithPath("page").type(NUMBER).description("페이지 번호") + queryParameters( + parameterWithName("page").description("페이지 번호") ), responseFields( fieldWithPath("orders").type(ARRAY).description("주문 목록"), diff --git a/src/test/java/com/prgrms/nabmart/global/auth/oauth/client/OAuthRestClientTest.java b/src/test/java/com/prgrms/nabmart/global/auth/oauth/client/OAuthRestClientTest.java new file mode 100644 index 000000000..1c34e15e2 --- /dev/null +++ b/src/test/java/com/prgrms/nabmart/global/auth/oauth/client/OAuthRestClientTest.java @@ -0,0 +1,217 @@ +package com.prgrms.nabmart.global.auth.oauth.client; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.BDDMockito.given; +import static org.mockito.BDDMockito.then; +import static org.mockito.Mockito.times; + +import com.prgrms.nabmart.domain.user.UserGrade; +import com.prgrms.nabmart.domain.user.UserRole; +import com.prgrms.nabmart.domain.user.service.response.FindUserDetailResponse; +import com.prgrms.nabmart.global.auth.oauth.OAuthProvider; +import com.prgrms.nabmart.global.auth.oauth.constant.OAuthConstant; +import com.prgrms.nabmart.global.infrastructure.ApiService; +import java.time.Instant; +import java.util.HashMap; +import java.util.Map; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +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 org.springframework.security.oauth2.client.OAuth2AuthorizedClient; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService; +import org.springframework.security.oauth2.client.registration.ClientRegistration; +import org.springframework.security.oauth2.core.AuthorizationGrantType; +import org.springframework.security.oauth2.core.ClientAuthenticationMethod; +import org.springframework.security.oauth2.core.OAuth2AccessToken; +import org.springframework.security.oauth2.core.OAuth2AccessToken.TokenType; +import org.springframework.security.oauth2.core.OAuth2RefreshToken; + +@ExtendWith(MockitoExtension.class) +class OAuthRestClientTest { + + @InjectMocks + OAuthRestClient oAuthRestClient; + + @Mock + ApiService apiService; + + @Mock + OAuth2AuthorizedClientService authorizedClientService; + + private OAuth2AuthorizedClient oAuth2AuthorizedClient(String provider, int tokenExpiresMillis) { + ClientRegistration clientRegistration = ClientRegistration.withRegistrationId(provider) + .clientId("clientId") + .clientSecret("clientSecret") + .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_JWT) + .authorizationGrantType(AuthorizationGrantType.JWT_BEARER) + .redirectUri("https://redirectURL.com") + .build(); + Instant now = Instant.now(); + OAuth2AccessToken accessToken + = new OAuth2AccessToken( + TokenType.BEARER, + "accessToken", + now, + now.plusMillis(tokenExpiresMillis)); + OAuth2RefreshToken refreshToken + = new OAuth2RefreshToken("refreshToken", now, now.plusSeconds(60)); + return new OAuth2AuthorizedClient(clientRegistration, "principalName", accessToken, + refreshToken); + } + + private FindUserDetailResponse findUserDetailResponse(String provider) { + return new FindUserDetailResponse(1L, "nickname", "email@email.com", provider, + "providerId", UserRole.ROLE_USER, UserGrade.NORMAL); + } + + private Map kakaoTokenRefreshResponse() { + int expiresIn = Long.valueOf(Instant.now().getEpochSecond()).intValue(); + + Map tokenRefreshResponse = new HashMap<>(); + tokenRefreshResponse.put(OAuthConstant.ACCESS_TOKEN, "accessToken"); + tokenRefreshResponse.put(OAuthConstant.EXPIRES_IN, expiresIn); + tokenRefreshResponse.put(OAuthConstant.REFRESH_TOKEN, "refreshToken"); + return tokenRefreshResponse; + } + + private Map naverTokenRefreshResponse() { + String expiresIn = Long.valueOf(Instant.now().getEpochSecond()).toString(); + + Map naverResponse = new HashMap<>(); + naverResponse.put(OAuthConstant.ACCESS_TOKEN, "accessToken"); + naverResponse.put(OAuthConstant.EXPIRES_IN, expiresIn); + naverResponse.put(OAuthConstant.REFRESH_TOKEN, "refreshToken"); + return naverResponse; + } + + @Nested + @DisplayName("callUnlinkOAuthUser 메서드 실행 시") + class CallUnlinkOAuthUserTest { + + @Test + @DisplayName("성공: 카카오, 인증 서버 액세스 토큰 만료 되지 않음") + void successKakao() { + //given + String kakaoProvider = OAuthProvider.KAKAO.getName(); + OAuth2AuthorizedClient oAuth2AuthorizedClient = oAuth2AuthorizedClient(kakaoProvider, + 1000); + Map response = new HashMap<>(); + response.put(OAuthConstant.ID, "providerId"); + FindUserDetailResponse userDetailResponse = findUserDetailResponse(kakaoProvider); + + given(authorizedClientService.loadAuthorizedClient(any(), any())).willReturn( + oAuth2AuthorizedClient); + given(apiService.getResult(any(), any(), any(), any())) + .willReturn(response); + + //when + oAuthRestClient.callUnlinkOAuthUser(userDetailResponse); + + //then + then(authorizedClientService).should().removeAuthorizedClient(eq(kakaoProvider), any()); + then(authorizedClientService).should(times(0)).saveAuthorizedClient(any(), any()); + } + @Test + @Disabled("랜덤하게 실패. 일정 시간 대기시킬 수 있는 도구가 필요.") + @DisplayName("성공: 카카오, 인증 서버 액세스 토큰 만료됨") + void successKakaoWhenAccessTokenExpired() { + //given + String kakaoProvider = OAuthProvider.KAKAO.getName(); + int tokenExpiredSeconds = 1; + OAuth2AuthorizedClient oAuth2AuthorizedClient = oAuth2AuthorizedClient(kakaoProvider, + tokenExpiredSeconds); + Map unlinkResponse = new HashMap<>(); + unlinkResponse.put(OAuthConstant.ID, "providerId"); + Map tokenRefreshResponse = kakaoTokenRefreshResponse(); + FindUserDetailResponse userDetailResponse = findUserDetailResponse(kakaoProvider); + + given(authorizedClientService.loadAuthorizedClient(any(), any())).willReturn( + oAuth2AuthorizedClient); + given(apiService.getResult(any(), any(), any(), any())) + .willReturn(tokenRefreshResponse) + .willReturn(unlinkResponse); + + //when + oAuthRestClient.callUnlinkOAuthUser(userDetailResponse); + + //then + then(authorizedClientService).should().removeAuthorizedClient(eq(kakaoProvider), any()); + then(authorizedClientService).should().saveAuthorizedClient(any(), any()); + } + + @Test + @DisplayName("성공: 네이버, 인증 액세스 토큰 만료되지 않음") + void successNaver() { + //given + String naverProvider = OAuthProvider.NAVER.getName(); + OAuth2AuthorizedClient oAuth2AuthorizedClient = oAuth2AuthorizedClient(naverProvider, + 1000); + Map response = new HashMap<>(); + response.put(OAuthConstant.RESULT, OAuthConstant.SUCCESS); + FindUserDetailResponse userDetailResponse = findUserDetailResponse(naverProvider); + + given(authorizedClientService.loadAuthorizedClient(any(), any())).willReturn( + oAuth2AuthorizedClient); + given(apiService.getResult(any(), any(), any(), any())) + .willReturn(response); + + //when + oAuthRestClient.callUnlinkOAuthUser(userDetailResponse); + + //then + then(authorizedClientService).should().removeAuthorizedClient(eq(naverProvider), any()); + then(authorizedClientService).should(times(0)).saveAuthorizedClient(any(), any()); + } + + } + + @Nested + @DisplayName("callRefreshAccessToken 메서드 실행 시") + class CallRefreshAccessTokenTest { + + @Test + @DisplayName("성공: 카카오") + void successKakao() { + //given + String kakaoProvider = OAuthProvider.KAKAO.getName(); + OAuth2AuthorizedClient authorizedClient = oAuth2AuthorizedClient(kakaoProvider, 1000); + Map kakaoResponse = kakaoTokenRefreshResponse(); + FindUserDetailResponse userDetailResponse = findUserDetailResponse(kakaoProvider); + + given(authorizedClientService.loadAuthorizedClient(any(), any())).willReturn( + authorizedClient); + given(apiService.getResult(any(), any(), any(), any())).willReturn(kakaoResponse); + + //when + oAuthRestClient.callRefreshAccessToken(userDetailResponse); + + //then + then(authorizedClientService).should().saveAuthorizedClient(any(), any()); + } + @Test + @DisplayName("성공: 네이버") + void successNaver() { + //given + String naverProvider = OAuthProvider.NAVER.getName(); + OAuth2AuthorizedClient authorizedClient = oAuth2AuthorizedClient(naverProvider, 1000); + Map naverResponse = naverTokenRefreshResponse(); + FindUserDetailResponse userDetailResponse = findUserDetailResponse(naverProvider); + + given(authorizedClientService.loadAuthorizedClient(any(), any())).willReturn( + authorizedClient); + given(apiService.getResult(any(), any(), any(), any())).willReturn(naverResponse); + + //when + oAuthRestClient.callRefreshAccessToken(userDetailResponse); + + //then + then(authorizedClientService).should().saveAuthorizedClient(any(), any()); + } + } +}