Skip to content

Commit

Permalink
refactor: �OAuth API 호출을 트랜잭션 범위에서 분리 (#471)
Browse files Browse the repository at this point in the history
* refactor: AuthServiceFacade 적용

* test: AuthServiceFacade를 모킹으로 분리

* test: OAuth API 생성 메서드명 통일

* refactor: 서드파티 성공 응답 fixture 생성

* refactor: AuthControllerTest로 네이밍 변경
  • Loading branch information
iamjooon2 authored Oct 17, 2023
1 parent ac4726e commit b0ad7ac
Show file tree
Hide file tree
Showing 11 changed files with 256 additions and 131 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,13 @@
@RequiredArgsConstructor
public class AuthService {

private final OAuthClient oAuthClient;
private final JwtProvider jwtProvider;
private final MemberRepository memberRepository;
private final RefreshTokenRepository refreshTokenRepository;

public TokenDto login(String authCode) {
String accessToken = oAuthClient.getAccessToken(authCode);
OAuthMemberResponse oAuthMemberResponse = oAuthClient.getMember(accessToken);

public TokenDto login(OAuthMemberResponse oAuthMemberResponse) {
Member member = memberRepository.findByEmail(oAuthMemberResponse.getEmail())
.orElseGet(() -> memberRepository.save(oAuthMemberResponse.toMember()));

return createTokens(member.getId());
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package zipgo.auth.application;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import zipgo.auth.application.dto.OAuthMemberResponse;
import zipgo.auth.dto.TokenDto;

@Service
@RequiredArgsConstructor
public class AuthServiceFacade {

private final AuthService authService;
private final OAuthClient oAuthClient;

public TokenDto login(String authCode) {
String accessToken = oAuthClient.getAccessToken(authCode);
OAuthMemberResponse oAuthMemberResponse = oAuthClient.getMember(accessToken);
return authService.login(oAuthMemberResponse);
}

public String renewAccessTokenBy(String refreshToken) {
return authService.renewAccessTokenBy(refreshToken);
}

public void logout(Long memberId) {
authService.logout(memberId);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import zipgo.auth.application.AuthService;
import zipgo.auth.application.AuthServiceFacade;
import zipgo.auth.dto.AccessTokenResponse;
import zipgo.auth.dto.AuthCredentials;
import zipgo.auth.dto.AuthResponse;
Expand All @@ -32,15 +32,15 @@
@RequiredArgsConstructor
public class AuthController {

private final AuthService authService;
private final AuthServiceFacade authServiceFacade;
private final JwtProvider jwtProvider;
private final RefreshTokenCookieProvider refreshTokenCookieProvider;
private final MemberQueryService memberQueryService;
private final PetQueryService petQueryService;

@PostMapping("/login")
public ResponseEntity<LoginResponse> login(@RequestParam("code") String authCode) {
TokenDto tokenDto = authService.login(authCode);
TokenDto tokenDto = authServiceFacade.login(authCode);
ResponseCookie cookie = refreshTokenCookieProvider.createCookie(tokenDto.refreshToken());

String memberId = jwtProvider.getPayload(tokenDto.accessToken());
Expand All @@ -54,13 +54,13 @@ public ResponseEntity<LoginResponse> login(@RequestParam("code") String authCode

@GetMapping("/refresh")
public ResponseEntity<AccessTokenResponse> renewTokens(@CookieValue(value = REFRESH_TOKEN) String refreshToken) {
String accessToken = authService.renewAccessTokenBy(refreshToken);
String accessToken = authServiceFacade.renewAccessTokenBy(refreshToken);
return ResponseEntity.ok(AccessTokenResponse.from(accessToken));
}

@PostMapping("/logout")
public ResponseEntity<Void> logout(@Auth AuthCredentials authCredentials) {
authService.logout(authCredentials.id());
authServiceFacade.logout(authCredentials.id());
ResponseCookie logoutCookie = refreshTokenCookieProvider.createLogoutCookie();
return ResponseEntity.ok()
.header(SET_COOKIE, logoutCookie.toString())
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package zipgo.auth.application;

import org.junit.jupiter.api.DisplayNameGeneration;
import org.junit.jupiter.api.DisplayNameGenerator;
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 zipgo.auth.application.dto.OAuthMemberResponse;
import zipgo.auth.application.fixture.MemberResponseSuccessFixture;
import zipgo.auth.dto.TokenDto;
import zipgo.auth.exception.OAuthResourceNotBringException;
import zipgo.auth.exception.OAuthTokenNotBringException;
import zipgo.auth.exception.TokenExpiredException;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.junit.jupiter.api.Assertions.assertAll;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
@SuppressWarnings("NonAsciiCharacters")
@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
class AuthServiceFacadeTest {

@Mock
private OAuthClient oAuthClient;

@Mock
private AuthService authService;

@InjectMocks
private AuthServiceFacade authServiceFacade;

@Test
void 로그인에_성공하면_토큰을_발급한다() {
// given
when(oAuthClient.getAccessToken("인가 코드"))
.thenReturn("엑세스 토큰");
OAuthMemberResponse 서드파티_사용자_응답 = new MemberResponseSuccessFixture();
when(oAuthClient.getMember("엑세스 토큰"))
.thenReturn(서드파티_사용자_응답);
when(authService.login(서드파티_사용자_응답))
.thenReturn(TokenDto.of("생성된 엑세스 토큰", "생성된 리프레시 토큰"));

// when
TokenDto 토큰 = authServiceFacade.login("인가 코드");

// then
assertAll(
() -> assertThat(토큰.accessToken()).isEqualTo("생성된 엑세스 토큰"),
() -> assertThat(토큰.refreshToken()).isEqualTo("생성된 리프레시 토큰")
);
}

@Test
void 엑세스_토큰을_가져오지_못하면_예외가_발생한다() {
// given
when(oAuthClient.getAccessToken("인가 코드"))
.thenThrow(new OAuthTokenNotBringException());

// expect
assertThatThrownBy(() -> authServiceFacade.login("인가 코드"))
.isInstanceOf(OAuthTokenNotBringException.class)
.hasMessageContaining("서드파티 서비스에서 토큰을 받아오지 못했습니다. 잠시후 다시 시도해주세요.");
}

@Test
void 사용자_정보를_가져오지_못하면_예외가_발생한다() {
// given
when(oAuthClient.getAccessToken("인가 코드"))
.thenReturn("엑세스 토큰");
when(oAuthClient.getMember("엑세스 토큰"))
.thenThrow(new OAuthResourceNotBringException());

// expect
assertThatThrownBy(() -> authServiceFacade.login("인가 코드"))
.isInstanceOf(OAuthResourceNotBringException.class)
.hasMessageContaining("서드파티 서비스에서 정보를 받아오지 못했습니다. 잠시후 다시 시도해주세요");
}


@Test
void 엑세스_토큰을_갱신할_수_있다() {
// given
when(authService.renewAccessTokenBy("리프레시 토큰"))
.thenReturn("갱신된 엑세스 토큰");
// when
String 리프레시_토큰 = authServiceFacade.renewAccessTokenBy("리프레시 토큰");

// then
assertThat(리프레시_토큰).isNotEmpty();
}

@Test
void 만료된_엑세스_토큰은_갱신시_예외가_발생한다() {
// given
when(authService.renewAccessTokenBy("리프레시 토큰"))
.thenThrow(new TokenExpiredException());
// expect
assertThatThrownBy(() -> authServiceFacade.renewAccessTokenBy("리프레시 토큰"))
.isInstanceOf(TokenExpiredException.class)
.hasMessageContaining("만료된 토큰입니다. 올바른 토큰으로 다시 시도해주세요.");
}

@Test
void 로그아웃_할_수_있다() {
// given
Long memberId = 123L;

// when
authServiceFacade.logout(memberId);

// then
verify(authService, times(1)).logout(memberId);
}

}
105 changes: 0 additions & 105 deletions backend/src/test/java/zipgo/auth/application/AuthServiceMockTest.java

This file was deleted.

Loading

0 comments on commit b0ad7ac

Please sign in to comment.