diff --git a/build.gradle b/build.gradle index d91e4aaa..978b5bd9 100644 --- a/build.gradle +++ b/build.gradle @@ -16,6 +16,12 @@ java { } } +test { + testLogging { + showStandardStreams = project.hasProperty("showLogs") + } +} + configurations { compileOnly { extendsFrom annotationProcessor diff --git a/src/main/java/com/kuit/findyou/domain/auth/service/IssueTokenService.java b/src/main/java/com/kuit/findyou/domain/auth/service/IssueTokenService.java new file mode 100644 index 00000000..d51302eb --- /dev/null +++ b/src/main/java/com/kuit/findyou/domain/auth/service/IssueTokenService.java @@ -0,0 +1,8 @@ +package com.kuit.findyou.domain.auth.service; + +import com.kuit.findyou.domain.user.model.Role; + +public interface IssueTokenService { + String issueAccessToken(Long userId, Role role); + String issueRefreshToken(Long userId); +} diff --git a/src/main/java/com/kuit/findyou/domain/auth/service/IssueTokenServiceImpl.java b/src/main/java/com/kuit/findyou/domain/auth/service/IssueTokenServiceImpl.java new file mode 100644 index 00000000..cabc0028 --- /dev/null +++ b/src/main/java/com/kuit/findyou/domain/auth/service/IssueTokenServiceImpl.java @@ -0,0 +1,26 @@ +package com.kuit.findyou.domain.auth.service; + +import com.kuit.findyou.domain.auth.repository.RedisRefreshTokenRepository; +import com.kuit.findyou.domain.user.model.Role; +import com.kuit.findyou.global.jwt.util.JwtUtil; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@RequiredArgsConstructor +@Service +public class IssueTokenServiceImpl implements IssueTokenService { + private final JwtUtil jwtUtil; + private final RedisRefreshTokenRepository redisRefreshTokenRepository; + + @Override + public String issueAccessToken(Long userId, Role role) { + return jwtUtil.createAccessJwt(userId, role); + } + + @Override + public String issueRefreshToken(Long userId) { + String refreshToken = jwtUtil.createRefreshJwt(userId); + redisRefreshTokenRepository.save(userId, refreshToken); + return refreshToken; + } +} diff --git a/src/main/java/com/kuit/findyou/domain/auth/service/LoginServiceImpl.java b/src/main/java/com/kuit/findyou/domain/auth/service/LoginServiceImpl.java index 068af01c..4e22c425 100644 --- a/src/main/java/com/kuit/findyou/domain/auth/service/LoginServiceImpl.java +++ b/src/main/java/com/kuit/findyou/domain/auth/service/LoginServiceImpl.java @@ -4,13 +4,11 @@ import com.kuit.findyou.domain.auth.dto.response.GuestLoginResponse; import com.kuit.findyou.domain.auth.dto.request.KakaoLoginRequest; import com.kuit.findyou.domain.auth.dto.response.KakaoLoginResponse; -import com.kuit.findyou.domain.auth.repository.RedisRefreshTokenRepository; import com.kuit.findyou.domain.user.constant.DefaultProfileImage; import com.kuit.findyou.domain.user.model.Role; import com.kuit.findyou.domain.user.model.User; import com.kuit.findyou.domain.user.repository.UserRepository; import com.kuit.findyou.global.common.exception.CustomException; -import com.kuit.findyou.global.jwt.util.JwtUtil; import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -23,18 +21,17 @@ @Service public class LoginServiceImpl implements LoginService { private final UserRepository userRepository; - private final RedisRefreshTokenRepository redisRefreshTokenRepository; - private final JwtUtil jwtUtil; + private final IssueTokenService issueTokenService; + public KakaoLoginResponse kakaoLogin(KakaoLoginRequest request) { log.info("[kakaoLogin] kakaoId = {}", request.kakaoId()); return userRepository.findByKakaoId(request.kakaoId()) - .map(loginUser -> { - String accessToken = jwtUtil.createAccessJwt(loginUser.getId(), loginUser.getRole()); - String refreshToken = jwtUtil.createRefreshJwt(loginUser.getId()); - redisRefreshTokenRepository.save(loginUser.getId(), refreshToken); + .map(user -> { + String accessToken = issueTokenService.issueAccessToken(user.getId(), user.getRole()); + String refreshToken = issueTokenService.issueRefreshToken(user.getId()); log.info("[kakaoLogin] 카카오 로그인 성공"); - return KakaoLoginResponse.fromUserAndTokens(loginUser, accessToken, refreshToken); + return KakaoLoginResponse.fromUserAndTokens(user, accessToken, refreshToken); }) .orElseGet(() -> { log.info("[kakaoLogin] 일치하는 유저가 없어서 카카오 로그인 실패"); @@ -67,9 +64,8 @@ public GuestLoginResponse guestLogin(GuestLoginRequest request) { } // 토큰 생성 - String accessToken = jwtUtil.createAccessJwt(user.getId(), user.getRole()); - String refreshToken = jwtUtil.createRefreshJwt(user.getId()); - redisRefreshTokenRepository.save(user.getId(), refreshToken); + String accessToken = issueTokenService.issueAccessToken(user.getId(), user.getRole()); + String refreshToken = issueTokenService.issueRefreshToken(user.getId()); log.info("[guestLogin] 게스트 로그인 성공"); return new GuestLoginResponse(user.getId(), accessToken, refreshToken); } diff --git a/src/main/java/com/kuit/findyou/domain/user/controller/UserController.java b/src/main/java/com/kuit/findyou/domain/user/controller/UserController.java index 91d49d89..7f9c9b1e 100644 --- a/src/main/java/com/kuit/findyou/domain/user/controller/UserController.java +++ b/src/main/java/com/kuit/findyou/domain/user/controller/UserController.java @@ -25,7 +25,6 @@ import lombok.extern.slf4j.Slf4j; import static com.kuit.findyou.global.common.swagger.SwaggerResponseDescription.*; -import static org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE; @Slf4j @RestController @@ -65,15 +64,12 @@ public BaseResponse retrieveViewedAnimals ( @Operation( summary = "회원정보 등록 API", description = """ - 회원 정보를 등록합니다. 회원 등록에 성공하면 유저 정보(식별자와 닉네임)와 엑세스 토큰을 얻을 수 있습니다. \n - **[중요] profileImageFile과 defaultProfileImageName 중 하나만 선택해야 합니다.** \n - - profileImageFile을 업로드하면 defaultProfileImageName은 무시됩니다. \n - - 둘 다 null이면 에러가 발생합니다. + 회원 정보를 등록합니다. 회원 등록에 성공하면 유저 정보(식별자와 닉네임)와 엑세스 토큰을 얻을 수 있습니다. """ ) @CustomExceptionDescription(REGISTER_USER) - @PostMapping(consumes = MULTIPART_FORM_DATA_VALUE) - public BaseResponse registerUser(@ModelAttribute RegisterUserRequest request){ + @PostMapping + public BaseResponse registerUser(@RequestBody RegisterUserRequest request){ log.info("[registerUser] kakaoId = {}", request.kakaoId()); return new BaseResponse<>(userServiceFacade.registerUser(request)); } @@ -142,21 +138,6 @@ public BaseResponse deleteInterestAnimal(@Parameter(hidden = true) @LoginU return BaseResponse.ok(null); } - @Operation( - summary = "프로필 이미지 변경 API", - description = "프로필 이미지 변경을 수행합니다. 기본이미지는 enum값 이름으로 저장, 사용자 업로드 이미지는 cdn url로 저장됩니다." - ) - @CustomExceptionDescription(CHANGE_PROFILE_IMAGE) - @PreAuthorize("hasRole('ROLE_USER')") - @PatchMapping(value = "/me/profile-image", consumes = MULTIPART_FORM_DATA_VALUE) - public BaseResponse changeProfileImage( - @LoginUserId Long userId, - @Valid @ModelAttribute ChangeProfileImageRequest req - ) { - userServiceFacade.changeProfileImage(userId, req); - return BaseResponse.ok(null); - } - @Operation( summary = "신고 내역 조회 API", description = """ diff --git a/src/main/java/com/kuit/findyou/domain/user/dto/request/RegisterUserRequest.java b/src/main/java/com/kuit/findyou/domain/user/dto/request/RegisterUserRequest.java index b9861154..57de8b1c 100644 --- a/src/main/java/com/kuit/findyou/domain/user/dto/request/RegisterUserRequest.java +++ b/src/main/java/com/kuit/findyou/domain/user/dto/request/RegisterUserRequest.java @@ -9,19 +9,6 @@ """ ) @Builder public record RegisterUserRequest( - @Schema(description = """ - 사용자 지정 프로필 이미지 파일 (기본 프로필을 사용하지 않을 경우 업로드) - """, - type = "string", - format = "binary", - nullable = true) - MultipartFile profileImageFile, - @Schema(description = """ - 기본 프로필 이미지 이름 (profileImageFile이 없을 경우 선택) - """, - example = "default", - nullable = true) - String defaultProfileImageName, @Schema(description = "회원 닉네임", example = "찾아유", required = true) diff --git a/src/main/java/com/kuit/findyou/domain/user/dto/response/GetUserProfileResponse.java b/src/main/java/com/kuit/findyou/domain/user/dto/response/GetUserProfileResponse.java index 81edb438..96f99403 100644 --- a/src/main/java/com/kuit/findyou/domain/user/dto/response/GetUserProfileResponse.java +++ b/src/main/java/com/kuit/findyou/domain/user/dto/response/GetUserProfileResponse.java @@ -5,8 +5,6 @@ @Schema(description = "마이페이지 프로필 조회 API 응답 DTO ") public record GetUserProfileResponse( @Schema(description = "닉네임", example = "유저1") - String nickname, - @Schema(description = "프로필 이미지", example = "image.png") - String profileImage + String nickname ) { } diff --git a/src/main/java/com/kuit/findyou/domain/user/dto/response/RegisterUserResponse.java b/src/main/java/com/kuit/findyou/domain/user/dto/response/RegisterUserResponse.java index fe5f4db5..18a622cf 100644 --- a/src/main/java/com/kuit/findyou/domain/user/dto/response/RegisterUserResponse.java +++ b/src/main/java/com/kuit/findyou/domain/user/dto/response/RegisterUserResponse.java @@ -11,7 +11,10 @@ public record RegisterUserResponse( example = "찾아유") String nickname, @Schema(description = "엑세스 토큰", - example = "accessToken") - String accessToken + example = "aaaa.bbbb.ccc") + String accessToken, + @Schema(description = "리프레시 토큰", + example = "aaaa.bbbb.ccc") + String refreshToken ) { } diff --git a/src/main/java/com/kuit/findyou/domain/user/model/User.java b/src/main/java/com/kuit/findyou/domain/user/model/User.java index 962345f4..04c01d27 100644 --- a/src/main/java/com/kuit/findyou/domain/user/model/User.java +++ b/src/main/java/com/kuit/findyou/domain/user/model/User.java @@ -11,8 +11,6 @@ import com.kuit.findyou.global.common.model.BaseEntity; import jakarta.persistence.*; import lombok.*; -import org.hibernate.annotations.SQLDelete; -import org.hibernate.annotations.SQLRestriction; import java.util.ArrayList; import java.util.List; @@ -100,7 +98,7 @@ public void addInterestReport(InterestReport interestReport) { public void addSubscribe(Subscribe subscribe) { subscribes.add(subscribe); } public void setFcmToken(FcmToken fcmToken) {this.fcmToken = fcmToken;} - public void upgradeToMember(Long kakaoId, String nickname, String profileImageUrl){ + public void upgradeToMember(Long kakaoId, String nickname){ // 비회원이어야 회원이 될 수 있음 if(this.role != Role.GUEST){ throw new CustomException(ALREADY_REGISTERED_USER); @@ -108,7 +106,6 @@ public void upgradeToMember(Long kakaoId, String nickname, String profileImageUr this.kakaoId = kakaoId; this.name = nickname; - this.profileImageUrl = profileImageUrl; this.role = Role.USER; } @@ -119,5 +116,4 @@ public boolean isGuest(){ public void changeNickname(String newNickname) { this.name = newNickname; } - public void changeProfileImage(String newImage) {this.profileImageUrl = newImage;} } diff --git a/src/main/java/com/kuit/findyou/domain/user/service/change_profileImage/ChangeProfileImageService.java b/src/main/java/com/kuit/findyou/domain/user/service/change_profileImage/ChangeProfileImageService.java deleted file mode 100644 index bf093d26..00000000 --- a/src/main/java/com/kuit/findyou/domain/user/service/change_profileImage/ChangeProfileImageService.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.kuit.findyou.domain.user.service.change_profileImage; - -import com.kuit.findyou.domain.user.dto.request.ChangeProfileImageRequest; - -public interface ChangeProfileImageService { - void changeProfileImage(Long userId, ChangeProfileImageRequest request); -} diff --git a/src/main/java/com/kuit/findyou/domain/user/service/change_profileImage/ChangeProfileImageServiceImpl.java b/src/main/java/com/kuit/findyou/domain/user/service/change_profileImage/ChangeProfileImageServiceImpl.java deleted file mode 100644 index f3a2d885..00000000 --- a/src/main/java/com/kuit/findyou/domain/user/service/change_profileImage/ChangeProfileImageServiceImpl.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.kuit.findyou.domain.user.service.change_profileImage; - -import com.kuit.findyou.domain.user.constant.DefaultProfileImage; -import com.kuit.findyou.domain.user.dto.request.ChangeProfileImageRequest; -import com.kuit.findyou.domain.user.model.User; -import com.kuit.findyou.domain.user.repository.UserRepository; -import com.kuit.findyou.global.common.exception.CustomException; -import com.kuit.findyou.global.infrastructure.FileUploadingFailedException; -import com.kuit.findyou.global.infrastructure.ImageUploader; -import jakarta.persistence.EntityNotFoundException; -import jakarta.transaction.Transactional; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -import java.net.URI; -import java.net.URISyntaxException; -import java.util.Arrays; - -import static com.kuit.findyou.global.common.response.status.BaseExceptionResponseStatus.*; - -@Slf4j -@Service -@RequiredArgsConstructor -public class ChangeProfileImageServiceImpl implements ChangeProfileImageService { - private final UserRepository userRepository; - private final ImageUploader imageUploader; - - - @Override - @Transactional - public void changeProfileImage(Long userId, ChangeProfileImageRequest request) { - try { - User user = userRepository.getReferenceById(userId); - - String toSave; - if (request.profileImageFile() != null) { - try { - toSave = imageUploader.upload(request.profileImageFile()); - } catch (FileUploadingFailedException e) { - throw new CustomException(IMAGE_UPLOAD_FAILED); - } - } else { - //enum 이름을 소문자로 저장 - toSave = Arrays.stream(DefaultProfileImage.values()) - .filter(v -> v.getName().equalsIgnoreCase(request.defaultProfileImageName())) - .findFirst() - .orElseThrow(() -> new CustomException(BAD_REQUEST)) - .getName(); - } - String oldImageUrl = user.getProfileImageUrl(); - user.changeProfileImage(toSave); - if (isUploadedFile(oldImageUrl)) { - String imageKey = extractImageKeyFromUrl(oldImageUrl); - imageUploader.delete(imageKey); - } - }catch (EntityNotFoundException e) { - throw new CustomException(USER_NOT_FOUND); - } - } - - private boolean isUploadedFile(String url) { - if (url == null) return false; - return Arrays.stream(DefaultProfileImage.values()) - .noneMatch(defaultImage -> defaultImage.getName().equalsIgnoreCase(url)); - } - - private String extractImageKeyFromUrl(String url) { - try { - return new URI(url).getPath().substring(1); - } catch (URISyntaxException e) { - throw new CustomException(BAD_REQUEST); - } - } -} diff --git a/src/main/java/com/kuit/findyou/domain/user/service/facade/UserServiceFacade.java b/src/main/java/com/kuit/findyou/domain/user/service/facade/UserServiceFacade.java index 324cd754..8136655c 100644 --- a/src/main/java/com/kuit/findyou/domain/user/service/facade/UserServiceFacade.java +++ b/src/main/java/com/kuit/findyou/domain/user/service/facade/UserServiceFacade.java @@ -3,13 +3,11 @@ import com.kuit.findyou.domain.report.dto.response.CardResponseDTO; import com.kuit.findyou.domain.user.dto.response.CheckGuestResponse; import com.kuit.findyou.domain.user.dto.response.GetUserProfileResponse; -import com.kuit.findyou.domain.user.dto.request.ChangeProfileImageRequest; import com.kuit.findyou.domain.user.dto.request.CheckDuplicateNicknameRequest; import com.kuit.findyou.domain.user.dto.request.RegisterUserRequest; import com.kuit.findyou.domain.user.dto.response.CheckDuplicateNicknameResponse; import com.kuit.findyou.domain.user.dto.response.RegisterUserResponse; import com.kuit.findyou.domain.user.service.change_nickname.ChangeNicknameService; -import com.kuit.findyou.domain.user.service.change_profileImage.ChangeProfileImageService; import com.kuit.findyou.domain.user.service.delete.DeleteUserService; import com.kuit.findyou.domain.user.service.interest_report.InterestReportService; import com.kuit.findyou.domain.user.service.query.QueryUserService; @@ -28,7 +26,6 @@ public class UserServiceFacade { private final QueryUserService queryUserService; private final ChangeNicknameService changeNicknameService; private final DeleteUserService deleteUserService; - private final ChangeProfileImageService changeProfileImageService; private final UserReportService userReportService; public CardResponseDTO retrieveViewedAnimals(Long lastId, Long userId) { @@ -63,8 +60,6 @@ public void deleteUser(Long userId) { deleteUserService.deleteUser(userId); } - public void changeProfileImage(Long userId, ChangeProfileImageRequest request){ changeProfileImageService.changeProfileImage(userId, request); } - public CardResponseDTO retrieveUserReports(Long userId, Long lastId){ return userReportService.retrieveUserReports(userId, lastId, 20); } diff --git a/src/main/java/com/kuit/findyou/domain/user/service/query/QueryUserServiceImpl.java b/src/main/java/com/kuit/findyou/domain/user/service/query/QueryUserServiceImpl.java index 523205fa..fd3927f9 100644 --- a/src/main/java/com/kuit/findyou/domain/user/service/query/QueryUserServiceImpl.java +++ b/src/main/java/com/kuit/findyou/domain/user/service/query/QueryUserServiceImpl.java @@ -28,7 +28,7 @@ public CheckDuplicateNicknameResponse checkDuplicateNickname(CheckDuplicateNickn @Override public GetUserProfileResponse getUserProfile(Long userId) { User user = userRepository.getReferenceById(userId); - return new GetUserProfileResponse(user.getName(), user.getProfileImageUrl()); + return new GetUserProfileResponse(user.getName()); } @Override diff --git a/src/main/java/com/kuit/findyou/domain/user/service/register/RegisterUserServiceImpl.java b/src/main/java/com/kuit/findyou/domain/user/service/register/RegisterUserServiceImpl.java index 55f1f2d0..4322b002 100644 --- a/src/main/java/com/kuit/findyou/domain/user/service/register/RegisterUserServiceImpl.java +++ b/src/main/java/com/kuit/findyou/domain/user/service/register/RegisterUserServiceImpl.java @@ -1,19 +1,15 @@ package com.kuit.findyou.domain.user.service.register; -import com.kuit.findyou.domain.user.constant.DefaultProfileImage; +import com.kuit.findyou.domain.auth.service.IssueTokenService; import com.kuit.findyou.domain.user.dto.request.RegisterUserRequest; import com.kuit.findyou.domain.user.dto.response.RegisterUserResponse; import com.kuit.findyou.domain.user.model.Role; import com.kuit.findyou.domain.user.model.User; import com.kuit.findyou.domain.user.repository.UserRepository; import com.kuit.findyou.global.common.exception.CustomException; -import com.kuit.findyou.global.infrastructure.FileUploadingFailedException; -import com.kuit.findyou.global.infrastructure.ImageUploader; -import com.kuit.findyou.global.jwt.util.JwtUtil; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; -import org.springframework.web.multipart.MultipartFile; import static com.kuit.findyou.global.common.response.status.BaseExceptionResponseStatus.*; @@ -22,9 +18,7 @@ @Service public class RegisterUserServiceImpl implements RegisterUserService { private final UserRepository userRepository; - private final ImageUploader imageUploader; - private final JwtUtil jwtUtil; - + private final IssueTokenService issueTokenService; @Override public RegisterUserResponse registerUser(RegisterUserRequest request) { // 카카오 Id가 중복되는 사용자가 있는지 확인 @@ -33,73 +27,32 @@ public RegisterUserResponse registerUser(RegisterUserRequest request) { throw new CustomException(ALREADY_REGISTERED_USER); } - // 비회원이었는지 확인한 후에 회원 정보 저장 - String profileImageUrl = getProfileImageUrl(request); - User user = userRepository.findByDeviceId(request.deviceId()) .map(existing -> { log.info("[registerUser] user with deviceId {} alreay exists", request.deviceId()); - existing.upgradeToMember(request.kakaoId(), request.nickname(), profileImageUrl); + existing.upgradeToMember(request.kakaoId(), request.nickname()); return existing; }) .orElseGet(()->{ log.info("[registerUser] user not found"); - return mapToUser(request, profileImageUrl); + return mapToUser(request); }); User save = userRepository.save(user); // 회원가입 완료 응답하기 - String accessToken = jwtUtil.createAccessJwt(save.getId(), save.getRole()); - return new RegisterUserResponse(save.getId(), save.getName(), accessToken); + String accessToken = issueTokenService.issueAccessToken(save.getId(), save.getRole()); + String refreshToken = issueTokenService.issueRefreshToken(save.getId()); + + return new RegisterUserResponse(save.getId(), save.getName(), accessToken, refreshToken); } - private User mapToUser(RegisterUserRequest request, String profileImageUrl) { + private User mapToUser(RegisterUserRequest request) { return User.builder() .kakaoId(request.kakaoId()) .name(request.nickname()) - .profileImageUrl(profileImageUrl) .role(Role.USER) .deviceId(request.deviceId()) .build(); } - - private String getProfileImageUrl(RegisterUserRequest request) { - // 프로필 이미지 설정 관련 검증 - MultipartFile profileImage = request.profileImageFile(); - String defaultProfileImageName = request.defaultProfileImageName(); - - if(validateProfileImage(profileImage, defaultProfileImageName)){ - // 요청이 잘못되었음 - throw new CustomException(BAD_REQUEST); - } - - // 인프라에 이미지 업로드 - if(!isEmptyProfileImageFile(profileImage)){ - try{ - return imageUploader.upload(profileImage); - } - catch (FileUploadingFailedException e){ - throw new CustomException(IMAGE_UPLOAD_FAILED); - } - } - - // 기본 이미지 이름 반환 - return defaultProfileImageName; - } - - private boolean validateProfileImage(MultipartFile profileFile, String defaultName) { - // 둘 다 잘못된 값이거나, 둘 다 올바른 값이면 잘못된 요청으로 간주 - boolean invalidName = isInvalidDefaultProfileImageName(defaultName); - boolean emptyFile = isEmptyProfileImageFile(profileFile); - return invalidName && emptyFile || !invalidName && !emptyFile; - } - - private boolean isInvalidDefaultProfileImageName(String name) { - return name == null || !DefaultProfileImage.validate(name); - } - - private boolean isEmptyProfileImageFile(MultipartFile file) { - return file == null || file.isEmpty(); - } } diff --git a/src/test/java/com/kuit/findyou/domain/auth/service/LoginServiceTest.java b/src/test/java/com/kuit/findyou/domain/auth/service/LoginServiceTest.java index b69c26af..e971bb58 100644 --- a/src/test/java/com/kuit/findyou/domain/auth/service/LoginServiceTest.java +++ b/src/test/java/com/kuit/findyou/domain/auth/service/LoginServiceTest.java @@ -33,9 +33,7 @@ class LoginServiceTest { @Mock private UserRepository userRepository; @Mock - private RedisRefreshTokenRepository redisRefreshTokenRepository; - @Mock - private JwtUtil jwtUtil; + private IssueTokenService issueTokenService; @DisplayName("카카오 id와 일치하는 사용자가 없다면 isFirstLogin을 true로 반환하여 회원가입을 유도한다") @Test @@ -57,21 +55,19 @@ void should_ReturnfirstLoginWithTrue_When_UserWithKakaoIdNotFound(){ void should_ReturnUserInfo_When_UserWithKakaoIdExists(){ // given final Long KAKAO_ID = 1234L; - final String ACCESS_TOKEN = "accessToken"; - final String REFRESH_TOKEN = "accessToken"; - final String NAME = "유저"; + String ACCESS_TOKEN = "accessToken"; + String REFRESH_TOKEN = "accessToken"; + String NAME = "유저"; User user = mockUser(NAME, Role.USER, KAKAO_ID); when(userRepository.findByKakaoId(KAKAO_ID)).thenReturn(Optional.of(user)); - when(jwtUtil.createAccessJwt(user.getId(), user.getRole())).thenReturn(ACCESS_TOKEN); - when(jwtUtil.createRefreshJwt(user.getId())).thenReturn(REFRESH_TOKEN); + when(issueTokenService.issueAccessToken(user.getId(), user.getRole())).thenReturn(ACCESS_TOKEN); + when(issueTokenService.issueRefreshToken(user.getId())).thenReturn(REFRESH_TOKEN); // when KakaoLoginResponse response = authService.kakaoLogin(new KakaoLoginRequest(KAKAO_ID)); // then - verify(redisRefreshTokenRepository, times(1)).save(anyLong(), anyString()); - assertThat(response.isFirstLogin()).isFalse(); assertThat(response.userInfo()).isNotNull(); assertThat(response.userInfo().userId()).isEqualTo(user.getId()); @@ -95,21 +91,20 @@ private User mockUser(String name, Role role, Long kakaoId){ @Test() void should_DoesNotSaveNewGuest_When_UserWithDeviceIdExists(){ // given - final String deviceId = "asdf-1234-asdf"; - final String accessToken = "accessToken"; - final String refreshToken = "refreshToken"; + String deviceId = "asdf-1234-asdf"; + String accessToken = "accessToken"; + String refreshToken = "refreshToken"; User user = mockUser("게스트", Role.GUEST, null); when(userRepository.findByDeviceId(eq(deviceId))).thenReturn(Optional.of(user)); - when(jwtUtil.createAccessJwt(anyLong(), any(Role.class))).thenReturn(accessToken); - when(jwtUtil.createRefreshJwt(anyLong())).thenReturn(refreshToken); + when(issueTokenService.issueAccessToken(anyLong(), any(Role.class))).thenReturn(accessToken); + when(issueTokenService.issueRefreshToken(anyLong())).thenReturn(refreshToken); // when GuestLoginResponse response = authService.guestLogin(new GuestLoginRequest(deviceId)); // then verify(userRepository, never()).save(any()); - verify(redisRefreshTokenRepository, times(1)).save(anyLong(), anyString()); assertThat(response.userId()).isEqualTo(user.getId()); assertThat(response.accessToken()).isEqualTo(accessToken); @@ -120,22 +115,21 @@ void should_DoesNotSaveNewGuest_When_UserWithDeviceIdExists(){ @Test() void should_SaveNewGuest_When_UserWithDeviceIdDoesNotExists(){ // given - final String deviceId = "asdf-1234-asdf"; - final String accessToken = "accessToken"; - final String refreshToken = "refreshToken"; + String deviceId = "asdf-1234-asdf"; + String accessToken = "accessToken"; + String refreshToken = "refreshToken"; User user = mockUser("게스트", Role.GUEST, null); when(userRepository.findByDeviceId(eq(deviceId))).thenReturn(Optional.empty()); when(userRepository.save(any())).thenReturn(user); - when(jwtUtil.createAccessJwt(anyLong(), any(Role.class))).thenReturn(accessToken); - when(jwtUtil.createRefreshJwt(anyLong())).thenReturn(refreshToken); + when(issueTokenService.issueAccessToken(anyLong(), any(Role.class))).thenReturn(accessToken); + when(issueTokenService.issueRefreshToken(anyLong())).thenReturn(refreshToken); // when GuestLoginResponse response = authService.guestLogin(new GuestLoginRequest(deviceId)); // then verify(userRepository).save(any(User.class)); - verify(redisRefreshTokenRepository, times(1)).save(anyLong(), anyString()); assertThat(response.userId()).isEqualTo(user.getId()); assertThat(response.accessToken()).isEqualTo(accessToken); @@ -146,8 +140,7 @@ void should_SaveNewGuest_When_UserWithDeviceIdDoesNotExists(){ @Test() void should_ThrowException_When_NonGuestUserLogsIn(){ // given - final String deviceId = "asdf-1234-asdf"; - final String accessToken = "accessToken"; + String deviceId = "asdf-1234-asdf"; User user = mockUser("게스트", Role.USER, null); when(userRepository.findByDeviceId(eq(deviceId))).thenReturn(Optional.of(user)); diff --git a/src/test/java/com/kuit/findyou/domain/user/controller/UserControllerTest.java b/src/test/java/com/kuit/findyou/domain/user/controller/UserControllerTest.java index 53751a44..15b1a966 100644 --- a/src/test/java/com/kuit/findyou/domain/user/controller/UserControllerTest.java +++ b/src/test/java/com/kuit/findyou/domain/user/controller/UserControllerTest.java @@ -5,6 +5,7 @@ import com.kuit.findyou.domain.report.model.WitnessReport; import com.kuit.findyou.domain.report.repository.InterestReportRepository; import com.kuit.findyou.domain.user.dto.request.CheckDuplicateNicknameRequest; +import com.kuit.findyou.domain.user.dto.request.RegisterUserRequest; import com.kuit.findyou.domain.user.dto.response.CheckDuplicateNicknameResponse; import com.kuit.findyou.domain.user.dto.response.CheckGuestResponse; import com.kuit.findyou.domain.user.dto.response.GetUserProfileResponse; @@ -15,6 +16,7 @@ import com.kuit.findyou.domain.user.repository.UserRepository; import com.kuit.findyou.global.common.util.DatabaseCleaner; import com.kuit.findyou.global.common.util.TestInitializer; +import com.kuit.findyou.global.config.RedisTestContainersConfig; import com.kuit.findyou.global.config.TestDatabaseConfig; import com.kuit.findyou.global.jwt.util.JwtUtil; import io.restassured.RestAssured; @@ -29,29 +31,22 @@ import org.springframework.context.annotation.Import; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.bean.override.mockito.MockitoBean; -import software.amazon.awssdk.core.sync.RequestBody; import software.amazon.awssdk.services.s3.S3Client; -import software.amazon.awssdk.services.s3.model.DeleteObjectRequest; -import software.amazon.awssdk.services.s3.model.PutObjectRequest; -import software.amazon.awssdk.services.s3.model.PutObjectResponse; import java.time.LocalDate; import java.util.Map; -import static com.kuit.findyou.domain.user.constant.DefaultProfileImage.PUPPY; import static com.kuit.findyou.global.common.response.status.BaseExceptionResponseStatus.*; -import static com.kuit.findyou.global.common.util.RestAssuredUtils.multipartText; import static io.restassured.RestAssured.given; import static org.assertj.core.api.Assertions.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.nullValue; -import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.*; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @TestInstance(TestInstance.Lifecycle.PER_CLASS) @ActiveProfiles("test") -@Import(TestDatabaseConfig.class) +@Import({RedisTestContainersConfig.class, TestDatabaseConfig.class}) class UserControllerTest { @LocalServerPort @@ -122,16 +117,16 @@ void retrieveViewedAnimals() { @Test void should_Succeed_When_registerAnyoneWhoFirstLoggedIn() { // given - final String NICKNAME = "유저1"; + String nickname = "유저1"; + Long kakaoId = 123456L; + String deviceId= "device-01"; // when RegisterUserResponse response = given() -// .log().all() - .contentType(ContentType.MULTIPART) - .multiPart(multipartText("defaultProfileImageName", "default")) - .multiPart(multipartText("nickname", NICKNAME)) - .multiPart(multipartText("kakaoId", "123456")) - .multiPart(multipartText("deviceId", "device-001")) + .log().all() + .contentType(ContentType.JSON) + .accept(ContentType.JSON) + .body(new RegisterUserRequest(nickname, kakaoId, deviceId)) .when() .post("/api/v2/users") .then() @@ -141,9 +136,11 @@ void should_Succeed_When_registerAnyoneWhoFirstLoggedIn() { .getObject("data", RegisterUserResponse.class); // then - Role role = jwtUtil.getRole(response.accessToken()); + assertThat(response.nickname()).isEqualTo(nickname); + assertThat(response.accessToken()).isNotBlank(); + assertThat(response.refreshToken()).isNotBlank(); - assertThat(response.nickname()).isEqualTo(NICKNAME); + Role role = jwtUtil.getRole(response.accessToken()); assertThat(role).isEqualTo(Role.USER); } @@ -497,116 +494,6 @@ void shouldSucceedToDeleteInterestAnimal_WhenItDoesNotExist() { assertThat(interestReportRepository.existsByReportIdAndUserId(report.getId(), user.getId())).isFalse(); } - @Test - @DisplayName("기본 이미지로 변경 성공") - void changeProfileImage_Default_Success() { - // given - User user = testInitializer.createTestUser(); - String token = jwtUtil.createAccessJwt(user.getId(), user.getRole()); - - // when & then - given() - .header("Authorization", "Bearer " + token) - .contentType(ContentType.MULTIPART) - .multiPart(multipartText("defaultProfileImageName", "chick")) - .when() - .patch("/api/v2/users/me/profile-image") - .then() - .statusCode(200) - .body("code", equalTo(SUCCESS.getCode())) - .body("message", equalTo(SUCCESS.getMessage())) - .body("data", nullValue()); - - User updated = userRepository.findById(user.getId()).orElseThrow(); - assertThat(updated.getProfileImageUrl()).isEqualTo("chick"); - } - - @Test - @DisplayName("파일 업로드로 변경 성공") - void changeProfileImage_File_Success() { - // given - User user = testInitializer.createTestUser(); - String token = jwtUtil.createAccessJwt(user.getId(), user.getRole()); - - // when & then - given() - .header("Authorization", "Bearer " + token) - .contentType(ContentType.MULTIPART) - .multiPart("profileImageFile", "p.jpg", "fake".getBytes(), "image/jpeg") - .when() - .patch("/api/v2/users/me/profile-image") - .then() - .statusCode(200) - .body("code", equalTo(SUCCESS.getCode())) - .body("message", equalTo(SUCCESS.getMessage())) - .body("data", nullValue()); - - User updated = userRepository.findById(user.getId()).orElseThrow(); - assertThat(updated.getProfileImageUrl()).startsWith("base-url"); - assertThat(updated.getProfileImageUrl()).endsWith("_p.jpg"); - } - - @Test - @DisplayName("둘 다 제공(파일+기본명) → 400") - void changeProfileImage_BothProvided_BadRequest() { - // given - User user = testInitializer.createTestUser(); - String token = jwtUtil.createAccessJwt(user.getId(), user.getRole()); - - given() - .header("Authorization", "Bearer " + token) - .contentType(ContentType.MULTIPART) - .multiPart(multipartText("defaultProfileImageName", "puppy")) - .multiPart("profileImageFile", "p.jpg", "fake".getBytes(), "image/jpeg") - .when() - .patch("/api/v2/users/me/profile-image") - .then() - .statusCode(200) - .body("success", equalTo(false)) - .body("code", equalTo(400)) - .body("message", equalTo("Invalid request")); - } - - @Test - @DisplayName("둘 다 제공 X → 400") - void changeProfileImage_NoneProvided_BadRequest() { - // given - User user = testInitializer.createTestUser(); - String token = jwtUtil.createAccessJwt(user.getId(), user.getRole()); - - given() - .header("Authorization", "Bearer " + token) - .contentType(ContentType.MULTIPART) - .multiPart("dummy", "dummy") - .when() - .patch("/api/v2/users/me/profile-image") - .then() - .statusCode(200) - .body("success", equalTo(false)) - .body("code", equalTo(400)) - .body("message", equalTo("Invalid request")); - } - - @Test - @DisplayName("잘못된 기본이미지 이름 → 400") - void changeProfileImage_InvalidDefaultName_BadRequest() { - // given - User user = testInitializer.createTestUser(); - String token = jwtUtil.createAccessJwt(user.getId(), user.getRole()); - - given() - .header("Authorization", "Bearer " + token) - .contentType(ContentType.MULTIPART) - .multiPart(multipartText("defaultProfileImageName", "cat")) - .when() - .patch("/api/v2/users/me/profile-image") - .then() - .statusCode(200) - .body("success", equalTo(false)) - .body("code", equalTo(BAD_REQUEST.getCode())) - .body("message", equalTo("Invalid request")); - } - @Test @DisplayName("사용자가 신고한 내역이 있다면 리턴한다.") void shouldReturnUserReports_WhenTheyExist() { @@ -687,93 +574,6 @@ void shouldReturnProfile_WhenUserExists() { // then assertThat(response.nickname()).isEqualTo(nickname); - assertThat(response.profileImage()).isEqualTo(profileImage); - } - - @Test - @DisplayName("프로필 이미지 변경 후, 마이페이지 조회 시 변경된 URL이 반환") - void changeProfileImage_and_VerifyWithMypageApi() { - User user = testInitializer.createTestUser(); - String token = jwtUtil.createAccessJwt(user.getId(), user.getRole()); - - when(s3Client.putObject(any(PutObjectRequest.class), any(RequestBody.class))) - .thenReturn(PutObjectResponse.builder().build()); - - // === 프로필 이미지 변경 API 호출 === - given() - .header("Authorization", "Bearer " + token) - .contentType(ContentType.MULTIPART) - .multiPart("profileImageFile", "p.jpg", "fake".getBytes(), "image/jpeg") - .when() - .patch("/api/v2/users/me/profile-image") - .then() - .statusCode(200) - .body("success", equalTo(true)); - - // === 마이페이지 조회 API 호출 === - String profileImageUrl = given() - .header("Authorization", "Bearer " + token) - .when() - .get("/api/v2/users/me") // 마이페이지 조회 API - .then() - .log().all() - .statusCode(200) - .extract() - .jsonPath() - .getString("data.profileImage"); - - // === 반환된 URL이 CDN 주소 형식을 따르는지 확인 === - assertThat(profileImageUrl).startsWith("base-url"); - } - - @Test - @DisplayName("프로필 - 기본이미지 -> 업로드 변경 시, 삭제 호출 없음") - void changeProfileImage_DefaultToUploaded_NoDelete() { - User user = testInitializer.createUserWithDefaultProfileImage(PUPPY); - - String token = jwtUtil.createAccessJwt(user.getId(), user.getRole()); - - when(s3Client.putObject(any(PutObjectRequest.class), any(RequestBody.class))) - .thenReturn(PutObjectResponse.builder().build()); - - given() - .header("Authorization", "Bearer " + token) - .contentType(ContentType.MULTIPART) - .multiPart("profileImageFile", "p.jpg", "fake".getBytes(), "image/jpeg") - .when() - .patch("/api/v2/users/me/profile-image") - .then() - .statusCode(200) - .body("success", equalTo(true)); - - verify(s3Client, times(0)).deleteObject(any(DeleteObjectRequest.class)); - } - - @Test - @DisplayName("프로필 - 업로드된 파일 -> 새 업로드 변경 시, 기존 파일 삭제 호출됨") - void changeProfileImage_FileToFile_DeleteOldFile() { - // given - //기존 프로필 이미지 존재 - User user = testInitializer.createUserWithUploadedProfileImage("base-url/old_profile.jpg"); - String token = jwtUtil.createAccessJwt(user.getId(), user.getRole()); - - when(s3Client.putObject(any(PutObjectRequest.class), any(RequestBody.class))) - .thenReturn(PutObjectResponse.builder().build()); - - // when - //새 프로필 업로드 - given() - .header("Authorization", "Bearer " + token) - .contentType(ContentType.MULTIPART) - .multiPart("profileImageFile", "new.jpg", "fake".getBytes(), "image/jpeg") - .when() - .patch("/api/v2/users/me/profile-image") - .then() - .statusCode(200) - .body("success", equalTo(true)); - - // then - verify(s3Client, times(1)).deleteObject(any(DeleteObjectRequest.class)); } @Test @@ -869,27 +669,6 @@ void shouldDenyRequest_WhenGuestDeletesAccount(){ .body("message", equalTo(FORBIDDEN.getMessage())); } - @Test - @DisplayName("비회원은 프로필 이미지를 변경할 수 없다") - void shouldDenyRequest_WhenGuestChangesProfileImage() { - // given - User guest = testInitializer.createTestGuest(); - String token = jwtUtil.createAccessJwt(guest.getId(), guest.getRole()); - - // when & then - given() - .header("Authorization", "Bearer " + token) - .contentType(ContentType.MULTIPART) - .multiPart(multipartText("defaultProfileImageName", "chick")) - .when() - .patch("/api/v2/users/me/profile-image") - .then() - .statusCode(403) - .body("success", equalTo(FORBIDDEN.getSuccess())) - .body("code", equalTo(FORBIDDEN.getCode())) - .body("message", equalTo(FORBIDDEN.getMessage())); - } - @Test @DisplayName("게스트는 게스트로 조회된다") void checkGuest_shouldReturnTrue_WhenGuest() { diff --git a/src/test/java/com/kuit/findyou/domain/user/repository/UserRepositoryTest.java b/src/test/java/com/kuit/findyou/domain/user/repository/UserRepositoryTest.java index 32fa2d8d..78be189e 100644 --- a/src/test/java/com/kuit/findyou/domain/user/repository/UserRepositoryTest.java +++ b/src/test/java/com/kuit/findyou/domain/user/repository/UserRepositoryTest.java @@ -225,44 +225,4 @@ private User createUser(String name, Role role, Long kakaoId, String deviceId) { .build(); return userRepository.save(build); } - - @Test - @DisplayName("더티체킹으로 기본 프로필 이미지(enum 문자열) 저장") - void dirtyChecking_SaveDefaultProfileName() { - // given - User user = userRepository.save(User.builder() - .name("유저") - .role(Role.USER) - .deviceId("dev-1") - .build()); - - // when - user.changeProfileImage("puppy"); - em.flush(); - em.clear(); - - // then - User found = userRepository.findById(user.getId()).orElseThrow(); - assertThat(found.getProfileImageUrl()).isEqualTo("puppy"); - } - - @Test - @DisplayName("더티체킹으로 CDN URL이 저장") - void dirtyChecking_SaveCdnUrl() { - // given - User user = userRepository.save(User.builder() - .name("유저") - .role(Role.USER) - .deviceId("dev-2") - .build()); - - // when - user.changeProfileImage("https://cdn.example/profile.jpg"); - em.flush(); - em.clear(); - - // then - User found = userRepository.findById(user.getId()).orElseThrow(); - assertThat(found.getProfileImageUrl()).isEqualTo("https://cdn.example/profile.jpg"); - } } \ No newline at end of file diff --git a/src/test/java/com/kuit/findyou/domain/user/service/ChangeProfileImageServiceTest.java b/src/test/java/com/kuit/findyou/domain/user/service/ChangeProfileImageServiceTest.java deleted file mode 100644 index beda325b..00000000 --- a/src/test/java/com/kuit/findyou/domain/user/service/ChangeProfileImageServiceTest.java +++ /dev/null @@ -1,102 +0,0 @@ -package com.kuit.findyou.domain.user.service; - -import com.kuit.findyou.domain.user.dto.request.ChangeProfileImageRequest; -import com.kuit.findyou.domain.user.model.Role; -import com.kuit.findyou.domain.user.model.User; -import com.kuit.findyou.domain.user.repository.UserRepository; -import com.kuit.findyou.domain.user.service.change_profileImage.ChangeProfileImageServiceImpl; -import com.kuit.findyou.global.common.exception.CustomException; -import com.kuit.findyou.global.infrastructure.FileUploadingFailedException; -import com.kuit.findyou.global.infrastructure.ImageUploader; -import jakarta.persistence.EntityNotFoundException; -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 org.springframework.mock.web.MockMultipartFile; - -import static com.kuit.findyou.global.common.response.status.BaseExceptionResponseStatus.IMAGE_UPLOAD_FAILED; -import static com.kuit.findyou.global.common.response.status.BaseExceptionResponseStatus.USER_NOT_FOUND; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.when; - -@ExtendWith(MockitoExtension.class) -public class ChangeProfileImageServiceTest { - @InjectMocks - ChangeProfileImageServiceImpl service; - @Mock - UserRepository userRepository; - @Mock - ImageUploader imageUploader; - - @Test - @DisplayName("기본 프로필(enum)로 변경 성공") - void changeToDefaultProfileImage_Success() { - // given - User user = User.builder() - .id(1L).name("유저").role(Role.USER).deviceId("1234").build(); - - when(userRepository.getReferenceById(1L)).thenReturn(user); - - ChangeProfileImageRequest req = new ChangeProfileImageRequest(null, "chick"); - - // when - service.changeProfileImage(1L, req); - - // then - assertThat(user.getProfileImageUrl()).isEqualTo("chick"); - } - - @Test - @DisplayName("파일 업로드로 변경 성공") - void changeToUploadedImage_Success() { - // given - User user = User.builder() - .id(1L).name("유저").role(Role.USER).deviceId("dev").build(); - - when(userRepository.getReferenceById(1L)).thenReturn(user); - when(imageUploader.upload(any())).thenReturn("https://cdn.test/uploaded.jpg"); - - MockMultipartFile file = new MockMultipartFile( - "profileImageFile", "p.jpg", "image/jpeg", "x".getBytes()); - ChangeProfileImageRequest req = new ChangeProfileImageRequest(file, null); - - // when - service.changeProfileImage(1L, req); - - // then - assertThat(user.getProfileImageUrl()).isEqualTo("https://cdn.test/uploaded.jpg"); - } - - @Test - @DisplayName("존재하지 않는 사용자이면 USER_NOT_FOUND") - void userNotFound_Throws() { - when(userRepository.getReferenceById(99L)).thenThrow(new EntityNotFoundException()); - ChangeProfileImageRequest req = new ChangeProfileImageRequest(null, "puppy"); - - assertThatThrownBy(() -> service.changeProfileImage(99L, req)) - .isInstanceOf(CustomException.class) - .hasMessageContaining(USER_NOT_FOUND.getMessage()); - } - - @Test - @DisplayName("이미지 업로드 실패 시 IMAGE_UPLOAD_FAILED") - void uploadFailed_Throws() { - User user = User.builder() - .id(1L).name("유저").role(Role.USER).deviceId("1234").build(); - when(userRepository.getReferenceById(1L)).thenReturn(user); - when(imageUploader.upload(any())).thenThrow(new FileUploadingFailedException("S3 업로드 실패")); - - MockMultipartFile file = new MockMultipartFile( - "profileImageFile", "p.jpg", "image/jpeg", "x".getBytes()); - ChangeProfileImageRequest req = new ChangeProfileImageRequest(file, null); - - assertThatThrownBy(() -> service.changeProfileImage(1L, req)) - .isInstanceOf(CustomException.class) - .hasMessageContaining(IMAGE_UPLOAD_FAILED.getMessage()); - } -} diff --git a/src/test/java/com/kuit/findyou/domain/user/service/UserServiceTest.java b/src/test/java/com/kuit/findyou/domain/user/service/UserServiceTest.java deleted file mode 100644 index 0e97f9c9..00000000 --- a/src/test/java/com/kuit/findyou/domain/user/service/UserServiceTest.java +++ /dev/null @@ -1,216 +0,0 @@ -package com.kuit.findyou.domain.user.service; - -import com.kuit.findyou.domain.user.dto.request.RegisterUserRequest; -import com.kuit.findyou.domain.user.dto.response.RegisterUserResponse; -import com.kuit.findyou.domain.user.model.User; -import com.kuit.findyou.domain.user.repository.UserRepository; -import com.kuit.findyou.domain.user.service.register.RegisterUserServiceImpl; -import com.kuit.findyou.global.common.exception.CustomException; -import com.kuit.findyou.global.infrastructure.FileUploadingFailedException; -import com.kuit.findyou.global.infrastructure.ImageUploader; -import com.kuit.findyou.global.jwt.util.JwtUtil; -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 org.springframework.mock.web.MockMultipartFile; - -import java.util.Optional; - -import static com.kuit.findyou.global.common.response.status.BaseExceptionResponseStatus.*; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.*; - -@ExtendWith(MockitoExtension.class) -class UserServiceTest { - @InjectMocks - private RegisterUserServiceImpl userService; - @Mock - private UserRepository userRepository; - @Mock - private ImageUploader imageUploader; - @Mock - private JwtUtil jwtUtil; - - @DisplayName("처음 로그인한 사용자가 회원등록을 하면 성공한다") - @Test - void should_Succeed_When_AnyoneWhoFirstLoggedInRegister(){ - // given - final Long USER_ID = 1L; - final String ACCESS_TOKEN = "accessToken"; - - RegisterUserRequest request = getRegisterUserRequestWithoutImage(); - - when(userRepository.findByKakaoId(request.kakaoId())).thenReturn(Optional.empty()); - when(userRepository.findByDeviceId(request.deviceId())).thenReturn(Optional.empty()); - when(userRepository.save(any())).thenReturn(User.builder() - .id(USER_ID) - .name(request.nickname()) - .build()); - - when(jwtUtil.createAccessJwt(any(), any())).thenReturn(ACCESS_TOKEN); - - // when - RegisterUserResponse response = userService.registerUser(request); - - // then - assertThat(response.userId()).isEqualTo(USER_ID); - assertThat(response.nickname()).isEqualTo(request.nickname()); - assertThat(response.accessToken()).isEqualTo(ACCESS_TOKEN); - } - - private static RegisterUserRequest getRegisterUserRequestWithoutImage() { - RegisterUserRequest request = RegisterUserRequest.builder() - .profileImageFile(null) - .defaultProfileImageName("default") - .nickname("유저1") - .kakaoId(1234L) - .deviceId("1234") - .build(); - return request; - } - - @DisplayName("비회원이 회원등록을 하면 성공한다") - @Test - void should_Succeed_When_GuestRegister(){ - // given - final Long USER_ID = 1L; - final String ACCESS_TOKEN = "accessToken"; - - RegisterUserRequest request = getRegisterUserRequestWithImage(); - - User user = mock(User.class); - - when(userRepository.findByKakaoId(request.kakaoId())).thenReturn(Optional.empty()); - when(userRepository.findByDeviceId(request.deviceId())).thenReturn(Optional.of(user)); - when(userRepository.save(any())).thenReturn(User.builder() - .id(USER_ID) - .name(request.nickname()) - .build()); - - when(imageUploader.upload(any())).thenReturn("image-url"); - - when(jwtUtil.createAccessJwt(any(), any())).thenReturn(ACCESS_TOKEN); - - // when - RegisterUserResponse response = userService.registerUser(request); - - // then - assertThat(response.userId()).isEqualTo(USER_ID); - assertThat(response.nickname()).isEqualTo(request.nickname()); - assertThat(response.accessToken()).isEqualTo(ACCESS_TOKEN); - - verify(user).upgradeToMember(eq(request.kakaoId()), eq(request.nickname()), eq("image-url")); - } - - @DisplayName("이미 가입한 회원이 회원등록을 하면 예외를 발생시킨다") - @Test - void should_ThrowException_When_ExistingUserRegister(){ - // given - final Long USER_ID = 1L; - - RegisterUserRequest request = getRegisterUserRequestWithoutImage(); - - User user = User.builder() - .id(USER_ID) - .build(); - - when(userRepository.findByKakaoId(request.kakaoId())).thenReturn(Optional.of(user)); - - // when - // then - assertThatThrownBy(() -> userService.registerUser(request)) - .isInstanceOf(CustomException.class) - .hasMessageContaining(ALREADY_REGISTERED_USER.getMessage()); - } - - @DisplayName("올바르지 않은 기본 프로필로 요청하면 예외가 발생한다") - @Test - void should_ThrowException_When_RequestContainsInvalidDefaultProfile(){ - // given - RegisterUserRequest request = getRegisterUserRequestWithWrongDefaultImageName(); - - when(userRepository.findByKakaoId(request.kakaoId())).thenReturn(Optional.empty()); - - // when - // then - assertThatThrownBy(() -> userService.registerUser(request)) - .isInstanceOf(CustomException.class) - .hasMessageContaining(BAD_REQUEST.getMessage()); - } - - private static RegisterUserRequest getRegisterUserRequestWithWrongDefaultImageName() { - RegisterUserRequest request = RegisterUserRequest.builder() - .profileImageFile(null) - .defaultProfileImageName("default-image") - .nickname("유저1") - .kakaoId(1234L) - .deviceId("1234") - .build(); - return request; - } - - @DisplayName("프로필 관련 내용 없이 요청하면 예외가 발생한다") - @Test - void should_ThrowException_When_RequestDoesNotContainProfile(){ - // given - RegisterUserRequest request = getRegisterUserRequestWithoutProfile(); - - when(userRepository.findByKakaoId(request.kakaoId())).thenReturn(Optional.empty()); - - // when - // then - assertThatThrownBy(() -> userService.registerUser(request)) - .isInstanceOf(CustomException.class) - .hasMessageContaining(BAD_REQUEST.getMessage()); - } - - private static RegisterUserRequest getRegisterUserRequestWithoutProfile() { - return RegisterUserRequest.builder() - .profileImageFile(null) - .defaultProfileImageName(null) - .nickname("유저1") - .kakaoId(1234L) - .deviceId("1234") - .build(); - } - - @DisplayName("이미지 업로드에 실패하면 예외가 발생한다") - @Test - void should_ThrowException_When_ImageUploadingFailed(){ - // given - RegisterUserRequest request = getRegisterUserRequestWithImage(); - - when(userRepository.findByKakaoId(request.kakaoId())).thenReturn(Optional.empty()); - when(imageUploader.upload(any())).thenThrow(new FileUploadingFailedException("S3 업로드 실패")); - - // when - // then - assertThatThrownBy(() -> userService.registerUser(request)) - .isInstanceOf(CustomException.class) - .hasMessageContaining(IMAGE_UPLOAD_FAILED.getMessage()); - } - - private static RegisterUserRequest getRegisterUserRequestWithImage() { - MockMultipartFile profileImage = new MockMultipartFile( - "profileImageFile", - "test.jpg", - "image/jpeg", - "fake-image-content".getBytes() - ); - - RegisterUserRequest request = RegisterUserRequest.builder() - .profileImageFile(profileImage) - .defaultProfileImageName(null) - .nickname("유저1") - .kakaoId(1234L) - .deviceId("1234") - .build(); - return request; - } -} \ No newline at end of file diff --git a/src/test/java/com/kuit/findyou/domain/user/service/query/QueryUserServiceTest.java b/src/test/java/com/kuit/findyou/domain/user/service/query/QueryUserServiceTest.java index 9226a370..f16e0d40 100644 --- a/src/test/java/com/kuit/findyou/domain/user/service/query/QueryUserServiceTest.java +++ b/src/test/java/com/kuit/findyou/domain/user/service/query/QueryUserServiceTest.java @@ -27,17 +27,14 @@ void shouldReturnUserProfile_WhenUserExists(){ // given final long userId = 1L; final String name = "name"; - final String profileImage = "default"; User mockUser = mock(User.class); when(userRepository.getReferenceById(anyLong())).thenReturn(mockUser); when(mockUser.getName()).thenReturn(name); - when(mockUser.getProfileImageUrl()).thenReturn(profileImage); // when GetUserProfileResponse userProfile = queryUserService.getUserProfile(userId); // then assertThat(userProfile.nickname()).isEqualTo(name); - assertThat(userProfile.profileImage()).isEqualTo(profileImage); } } \ No newline at end of file diff --git a/src/test/java/com/kuit/findyou/domain/user/service/register/RegisterUserServiceTest.java b/src/test/java/com/kuit/findyou/domain/user/service/register/RegisterUserServiceTest.java new file mode 100644 index 00000000..8f5ae88c --- /dev/null +++ b/src/test/java/com/kuit/findyou/domain/user/service/register/RegisterUserServiceTest.java @@ -0,0 +1,127 @@ +package com.kuit.findyou.domain.user.service.register; + +import com.kuit.findyou.domain.auth.service.IssueTokenService; +import com.kuit.findyou.domain.user.dto.request.RegisterUserRequest; +import com.kuit.findyou.domain.user.dto.response.RegisterUserResponse; +import com.kuit.findyou.domain.user.model.User; +import com.kuit.findyou.domain.user.repository.UserRepository; +import com.kuit.findyou.global.common.exception.CustomException; +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 java.util.Optional; + +import static com.kuit.findyou.global.common.response.status.BaseExceptionResponseStatus.*; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class RegisterUserServiceTest { + @InjectMocks + private RegisterUserServiceImpl userService; + @Mock + private UserRepository userRepository; + @Mock + private IssueTokenService issueTokenService; + + @DisplayName("처음 로그인한 사용자가 회원등록을 하면 성공한다") + @Test + void should_Succeed_When_AnyoneWhoFirstLoggedInRegister(){ + // given + final Long USER_ID = 1L; + final String ACCESS_TOKEN = "accessToken"; + final String REFRESH_TOKEN = "refreshToken"; + + RegisterUserRequest request = getRegisterUserRequest(); + + when(userRepository.findByKakaoId(request.kakaoId())).thenReturn(Optional.empty()); + when(userRepository.findByDeviceId(request.deviceId())).thenReturn(Optional.empty()); + when(userRepository.save(any())).thenReturn(User.builder() + .id(USER_ID) + .name(request.nickname()) + .build()); + + when(issueTokenService.issueAccessToken(any(), any())).thenReturn(ACCESS_TOKEN); + when(issueTokenService.issueRefreshToken(any())).thenReturn(REFRESH_TOKEN); + + // when + RegisterUserResponse response = userService.registerUser(request); + + // then + assertThat(response.userId()).isEqualTo(USER_ID); + assertThat(response.nickname()).isEqualTo(request.nickname()); + assertThat(response.accessToken()).isEqualTo(ACCESS_TOKEN); + assertThat(response.refreshToken()).isEqualTo(REFRESH_TOKEN); + } + + private static RegisterUserRequest getRegisterUserRequest() { + RegisterUserRequest request = RegisterUserRequest.builder() + .nickname("유저1") + .kakaoId(1234L) + .deviceId("1234") + .build(); + return request; + } + + @DisplayName("비회원이 회원등록을 하면 성공한다") + @Test + void should_Succeed_When_GuestRegister(){ + // given + final Long USER_ID = 1L; + final String ACCESS_TOKEN = "accessToken"; + final String REFRESH_TOKEN = "refreshToken"; + + RegisterUserRequest request = getRegisterUserRequest(); + + User user = mock(User.class); + + when(userRepository.findByKakaoId(request.kakaoId())).thenReturn(Optional.empty()); + when(userRepository.findByDeviceId(request.deviceId())).thenReturn(Optional.of(user)); + when(userRepository.save(any())).thenReturn(User.builder() + .id(USER_ID) + .name(request.nickname()) + .build()); + + when(issueTokenService.issueAccessToken(any(), any())).thenReturn(ACCESS_TOKEN); + when(issueTokenService.issueRefreshToken(any())).thenReturn(REFRESH_TOKEN); + + // when + RegisterUserResponse response = userService.registerUser(request); + + // then + verify(user).upgradeToMember(eq(request.kakaoId()), eq(request.nickname())); + + assertThat(response.userId()).isEqualTo(USER_ID); + assertThat(response.nickname()).isEqualTo(request.nickname()); + assertThat(response.accessToken()).isEqualTo(ACCESS_TOKEN); + assertThat(response.refreshToken()).isEqualTo(REFRESH_TOKEN); + } + + @DisplayName("이미 가입한 회원이 회원등록을 하면 예외를 발생시킨다") + @Test + void should_ThrowException_When_ExistingUserRegister(){ + // given + final Long USER_ID = 1L; + + RegisterUserRequest request = getRegisterUserRequest(); + + User user = User.builder() + .id(USER_ID) + .build(); + + when(userRepository.findByKakaoId(request.kakaoId())).thenReturn(Optional.of(user)); + + // when + // then + assertThatThrownBy(() -> userService.registerUser(request)) + .isInstanceOf(CustomException.class) + .hasMessageContaining(ALREADY_REGISTERED_USER.getMessage()); + } +} \ No newline at end of file diff --git a/src/test/java/com/kuit/findyou/global/common/util/TestInitializer.java b/src/test/java/com/kuit/findyou/global/common/util/TestInitializer.java index 59f26dff..705e9eea 100644 --- a/src/test/java/com/kuit/findyou/global/common/util/TestInitializer.java +++ b/src/test/java/com/kuit/findyou/global/common/util/TestInitializer.java @@ -404,23 +404,6 @@ public void createTestCities() { sigunguRepository.save(Sigungu.builder().name("해운대구").sido(busan).build()); } - public User createUserWithDefaultProfileImage(DefaultProfileImage img) { - User user = createTestUser(); - user.changeProfileImage(img.getName()); - return userRepository.save(user); - } - - public User createUserWithUploadedProfileImage(String imageUrl) { - User user = User.builder() - .name("홍길동") - .role(Role.USER) - .deviceId("device-uploaded") - .profileImageUrl(imageUrl) - .build(); - - return userRepository.save(user); - } - public User createTestGuest() { User user = User.builder() .name("게스트")