diff --git a/src/main/kotlin/com/routebox/routebox/application/user/GetMyProfileUseCase.kt b/src/main/kotlin/com/routebox/routebox/application/user/GetUserProfileUseCase.kt similarity index 56% rename from src/main/kotlin/com/routebox/routebox/application/user/GetMyProfileUseCase.kt rename to src/main/kotlin/com/routebox/routebox/application/user/GetUserProfileUseCase.kt index 5b84c66..c03cf10 100644 --- a/src/main/kotlin/com/routebox/routebox/application/user/GetMyProfileUseCase.kt +++ b/src/main/kotlin/com/routebox/routebox/application/user/GetUserProfileUseCase.kt @@ -1,16 +1,16 @@ package com.routebox.routebox.application.user -import com.routebox.routebox.application.user.dto.GetMyProfileResult +import com.routebox.routebox.application.user.dto.GetUserProfileResult import com.routebox.routebox.domain.user.UserService import org.springframework.stereotype.Component import org.springframework.transaction.annotation.Transactional @Component -class GetMyProfileUseCase(private val userService: UserService) { +class GetUserProfileUseCase(private val userService: UserService) { @Transactional(readOnly = true) - operator fun invoke(userId: Long): GetMyProfileResult { + operator fun invoke(userId: Long): GetUserProfileResult { val user = userService.getUserById(userId) - return GetMyProfileResult.from(user) + return GetUserProfileResult.from(user) } } diff --git a/src/main/kotlin/com/routebox/routebox/application/user/dto/GetMyProfileResult.kt b/src/main/kotlin/com/routebox/routebox/application/user/dto/GetUserProfileResult.kt similarity index 92% rename from src/main/kotlin/com/routebox/routebox/application/user/dto/GetMyProfileResult.kt rename to src/main/kotlin/com/routebox/routebox/application/user/dto/GetUserProfileResult.kt index 42bb21d..b445f55 100644 --- a/src/main/kotlin/com/routebox/routebox/application/user/dto/GetMyProfileResult.kt +++ b/src/main/kotlin/com/routebox/routebox/application/user/dto/GetUserProfileResult.kt @@ -5,7 +5,7 @@ import com.routebox.routebox.domain.user.constant.Gender import io.swagger.v3.oas.annotations.media.Schema import java.time.LocalDate -data class GetMyProfileResult( +data class GetUserProfileResult( @Schema(description = "Id(PK) of user", example = "1") val id: Long, @@ -25,7 +25,7 @@ data class GetMyProfileResult( val introduction: String, ) { companion object { - fun from(user: User) = GetMyProfileResult( + fun from(user: User) = GetUserProfileResult( id = user.id, profileImageUrl = user.profileImageUrl, nickname = user.nickname, diff --git a/src/main/kotlin/com/routebox/routebox/controller/user/UserController.kt b/src/main/kotlin/com/routebox/routebox/controller/user/UserController.kt index 9f142d9..4fda6f1 100644 --- a/src/main/kotlin/com/routebox/routebox/controller/user/UserController.kt +++ b/src/main/kotlin/com/routebox/routebox/controller/user/UserController.kt @@ -1,7 +1,7 @@ package com.routebox.routebox.controller.user import com.routebox.routebox.application.user.CheckNicknameAvailabilityUseCase -import com.routebox.routebox.application.user.GetMyProfileUseCase +import com.routebox.routebox.application.user.GetUserProfileUseCase import com.routebox.routebox.application.user.UpdateUserInfoUseCase import com.routebox.routebox.application.user.dto.UpdateUserInfoCommand import com.routebox.routebox.controller.user.dto.CheckNicknameAvailabilityResponse @@ -32,7 +32,7 @@ import org.springframework.web.bind.annotation.RestController @Validated @RequestMapping("/api") class UserController( - private val getMyProfileUseCase: GetMyProfileUseCase, + private val getUserProfileUseCase: GetUserProfileUseCase, private val checkNicknameAvailabilityUseCase: CheckNicknameAvailabilityUseCase, private val updateUserInfoUseCase: UpdateUserInfoUseCase, ) { @@ -40,10 +40,11 @@ class UserController( summary = "내 프로필 정보 조회", description = "
내 루트 개수, 취향 정보 등 추가 예정 (미구현)" + "
내 프로필 정보를 조회합니다.", + security = [SecurityRequirement(name = "access-token")], ) @GetMapping("/v1/users/me/profile") fun getMyProfile(@AuthenticationPrincipal principal: UserPrincipal): UserProfileResponse { - val myProfile = getMyProfileUseCase(userId = principal.userId) + val myProfile = getUserProfileUseCase(userId = principal.userId) return UserProfileResponse( id = myProfile.id, profileImageUrl = myProfile.profileImageUrl, @@ -54,6 +55,27 @@ class UserController( ) } + @Operation( + summary = "유저 프로필 정보 조회", + description = "
유저가 작성한 루트 개수, 취향 정보 등 추가 예정 (미구현)" + + "
특정 유저의 프로필 정보를 조회합니다.", + security = [SecurityRequirement(name = "access-token")], + ) + @GetMapping("/v1/users/{userId}/profile") + fun getUserProfile( + @Parameter(description = "프로필 정보를 조회할 유저의 id", example = "5") @PathVariable userId: Long, + ): UserProfileResponse { + val userProfile = getUserProfileUseCase(userId) + return UserProfileResponse( + id = userProfile.id, + profileImageUrl = userProfile.profileImageUrl, + nickname = userProfile.nickname, + gender = userProfile.gender, + birthDay = userProfile.birthDay, + introduction = userProfile.introduction, + ) + } + @Operation( summary = "닉네임 이용 가능 여부 확인", description = "닉네임의 이용 가능 여부를 확인합니다. 현재 사용중인 유저가 없다면 이용 가능한 닉네임입니다.", diff --git a/src/test/kotlin/com/routebox/routebox/application/user/GetMyProfileUseCaseTest.kt b/src/test/kotlin/com/routebox/routebox/application/user/GetUserProfileUseCaseTest.kt similarity index 96% rename from src/test/kotlin/com/routebox/routebox/application/user/GetMyProfileUseCaseTest.kt rename to src/test/kotlin/com/routebox/routebox/application/user/GetUserProfileUseCaseTest.kt index 2f4b5d5..75fb91c 100644 --- a/src/test/kotlin/com/routebox/routebox/application/user/GetMyProfileUseCaseTest.kt +++ b/src/test/kotlin/com/routebox/routebox/application/user/GetUserProfileUseCaseTest.kt @@ -17,10 +17,10 @@ import kotlin.random.Random import kotlin.test.Test @ExtendWith(MockitoExtension::class) -class GetMyProfileUseCaseTest { +class GetUserProfileUseCaseTest { @InjectMocks - lateinit var sut: GetMyProfileUseCase + lateinit var sut: GetUserProfileUseCase @Mock lateinit var userService: UserService diff --git a/src/test/kotlin/com/routebox/routebox/controller/user/UserControllerTest.kt b/src/test/kotlin/com/routebox/routebox/controller/user/UserControllerTest.kt index 0a01218..5bb30e1 100644 --- a/src/test/kotlin/com/routebox/routebox/controller/user/UserControllerTest.kt +++ b/src/test/kotlin/com/routebox/routebox/controller/user/UserControllerTest.kt @@ -2,9 +2,9 @@ package com.routebox.routebox.controller.user import com.fasterxml.jackson.databind.ObjectMapper import com.routebox.routebox.application.user.CheckNicknameAvailabilityUseCase -import com.routebox.routebox.application.user.GetMyProfileUseCase +import com.routebox.routebox.application.user.GetUserProfileUseCase import com.routebox.routebox.application.user.UpdateUserInfoUseCase -import com.routebox.routebox.application.user.dto.GetMyProfileResult +import com.routebox.routebox.application.user.dto.GetUserProfileResult import com.routebox.routebox.application.user.dto.UpdateUserInfoCommand import com.routebox.routebox.application.user.dto.UpdateUserInfoResult import com.routebox.routebox.config.ControllerTestConfig @@ -37,7 +37,7 @@ class UserControllerTest @Autowired constructor( private val mapper: ObjectMapper, ) { @MockBean - lateinit var getMyProfileUseCase: GetMyProfileUseCase + lateinit var getUserProfileUseCase: GetUserProfileUseCase @MockBean lateinit var updateUserInfoUseCase: UpdateUserInfoUseCase @@ -49,7 +49,7 @@ class UserControllerTest @Autowired constructor( fun `내 프로필 정보를 조회한다`() { // given val userId = Random.nextLong() - val expectedResult = GetMyProfileResult( + val expectedResult = GetUserProfileResult( id = userId, profileImageUrl = "https://user-profile-image", nickname = RandomStringUtils.random(5), @@ -57,7 +57,7 @@ class UserControllerTest @Autowired constructor( birthDay = LocalDate.of(2024, 1, 1), introduction = "I am...", ) - given(getMyProfileUseCase.invoke(userId)).willReturn(expectedResult) + given(getUserProfileUseCase.invoke(userId)).willReturn(expectedResult) // when & then mvc.perform( @@ -70,8 +70,37 @@ class UserControllerTest @Autowired constructor( .andExpect(jsonPath("$.gender").value(expectedResult.gender.toString())) .andExpect(jsonPath("$.birthDay").value(expectedResult.birthDay.toString())) .andExpect(jsonPath("$.introduction").value(expectedResult.introduction)) - then(getMyProfileUseCase).should().invoke(userId) - then(getMyProfileUseCase).shouldHaveNoMoreInteractions() + then(getUserProfileUseCase).should().invoke(userId) + then(getUserProfileUseCase).shouldHaveNoMoreInteractions() + } + + @Test + fun `특정 유저의 id가 주어지고, 주어진 id에 해당하는 유저의 프로필 정보를 조회한다`() { + // given + val targetUserId = Random.nextLong() + val expectedResult = GetUserProfileResult( + id = targetUserId, + profileImageUrl = "https://user-profile-image", + nickname = RandomStringUtils.random(5), + gender = Gender.PRIVATE, + birthDay = LocalDate.of(2024, 1, 1), + introduction = "I am...", + ) + given(getUserProfileUseCase.invoke(targetUserId)).willReturn(expectedResult) + + // when & then + mvc.perform( + get("/api/v1/users/{userId}/profile", targetUserId) + .with(user(createUserPrincipal(Random.nextLong()))), + ).andExpect(status().isOk) + .andExpect(jsonPath("$.id").value(expectedResult.id)) + .andExpect(jsonPath("$.profileImageUrl").value(expectedResult.profileImageUrl)) + .andExpect(jsonPath("$.nickname").value(expectedResult.nickname)) + .andExpect(jsonPath("$.gender").value(expectedResult.gender.toString())) + .andExpect(jsonPath("$.birthDay").value(expectedResult.birthDay.toString())) + .andExpect(jsonPath("$.introduction").value(expectedResult.introduction)) + then(getUserProfileUseCase).should().invoke(targetUserId) + then(getUserProfileUseCase).shouldHaveNoMoreInteractions() } @Test