From 78572e6e26302ea4d3688342a3b500b45ffe409f Mon Sep 17 00:00:00 2001 From: minahYu Date: Thu, 20 Jun 2024 11:08:16 +0900 Subject: [PATCH 01/11] =?UTF-8?q?feat:=20DeleteFriendResponse=20=EC=9E=90?= =?UTF-8?q?=EB=B0=94=ED=8C=8C=EC=9D=BC=EC=97=90=EC=84=9C=20=EC=BD=94?= =?UTF-8?q?=ED=8B=80=EB=A6=B0=ED=8C=8C=EC=9D=BC=EB=A1=9C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/kpring/user/dto/response/DeleteFriendResponse.java | 4 ---- .../kotlin/kpring/user/dto/response/DeleteFriendResponse.kt | 5 +++++ 2 files changed, 5 insertions(+), 4 deletions(-) delete mode 100644 user/src/main/java/kpring/user/dto/response/DeleteFriendResponse.java create mode 100644 user/src/main/kotlin/kpring/user/dto/response/DeleteFriendResponse.kt diff --git a/user/src/main/java/kpring/user/dto/response/DeleteFriendResponse.java b/user/src/main/java/kpring/user/dto/response/DeleteFriendResponse.java deleted file mode 100644 index dc7f9a83..00000000 --- a/user/src/main/java/kpring/user/dto/response/DeleteFriendResponse.java +++ /dev/null @@ -1,4 +0,0 @@ -package kpring.user.dto.response; - -public record DeleteFriendResponse() { -} diff --git a/user/src/main/kotlin/kpring/user/dto/response/DeleteFriendResponse.kt b/user/src/main/kotlin/kpring/user/dto/response/DeleteFriendResponse.kt new file mode 100644 index 00000000..6c1f1ed9 --- /dev/null +++ b/user/src/main/kotlin/kpring/user/dto/response/DeleteFriendResponse.kt @@ -0,0 +1,5 @@ +package kpring.user.dto.response + +data class DeleteFriendResponse( + val friendId: Long, +) From 6477bb02738961b912189912dc0a349c3228a84e Mon Sep 17 00:00:00 2001 From: minahYu Date: Thu, 20 Jun 2024 11:12:29 +0900 Subject: [PATCH 02/11] =?UTF-8?q?feat:=20UserErrorCode=20=EC=97=90?= =?UTF-8?q?=EB=9F=AC=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- user/src/main/kotlin/kpring/user/exception/UserErrorCode.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/user/src/main/kotlin/kpring/user/exception/UserErrorCode.kt b/user/src/main/kotlin/kpring/user/exception/UserErrorCode.kt index 8b8f15ae..a4450bcc 100644 --- a/user/src/main/kotlin/kpring/user/exception/UserErrorCode.kt +++ b/user/src/main/kotlin/kpring/user/exception/UserErrorCode.kt @@ -24,6 +24,7 @@ enum class UserErrorCode( "4032", "해당하는 친구신청이 없거나 이미 친구입니다.", ), + FRIEND_NOT_FOUND(HttpStatus.BAD_REQUEST, "4033", "해당하는 친구가 없습니다."), ; override fun message(): String = this.message From 0acbd31803e750c4db8ada04b4ed199ffaa7207d Mon Sep 17 00:00:00 2001 From: minahYu Date: Thu, 20 Jun 2024 11:12:55 +0900 Subject: [PATCH 03/11] =?UTF-8?q?feat:=20User=20=EC=97=94=ED=8B=B0?= =?UTF-8?q?=ED=8B=B0=EC=97=90=20removeFriendRelation=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- user/src/main/kotlin/kpring/user/entity/User.kt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/user/src/main/kotlin/kpring/user/entity/User.kt b/user/src/main/kotlin/kpring/user/entity/User.kt index 02f71211..076254a3 100644 --- a/user/src/main/kotlin/kpring/user/entity/User.kt +++ b/user/src/main/kotlin/kpring/user/entity/User.kt @@ -40,6 +40,11 @@ class User( friends.add(friendRelation) } + fun removeFriendRelation(friendRelation: Friend) { + friends.remove(friendRelation) + friendRelation.friend.friends.removeIf { it.friend == this } + } + fun updateInfo( request: UpdateUserProfileRequest, newPassword: String?, From 2c0a0a6b3aa569c75df79c1e3a75ce77493f1d46 Mon Sep 17 00:00:00 2001 From: minahYu Date: Thu, 20 Jun 2024 11:13:45 +0900 Subject: [PATCH 04/11] =?UTF-8?q?feat:=20FriendServiceImpl=20=EC=97=90=20d?= =?UTF-8?q?eleteFriend=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EC=BD=94=EB=93=9C?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kpring/user/service/FriendServiceImpl.kt | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/user/src/main/kotlin/kpring/user/service/FriendServiceImpl.kt b/user/src/main/kotlin/kpring/user/service/FriendServiceImpl.kt index 896ecefb..9ccbd4dc 100644 --- a/user/src/main/kotlin/kpring/user/service/FriendServiceImpl.kt +++ b/user/src/main/kotlin/kpring/user/service/FriendServiceImpl.kt @@ -66,7 +66,20 @@ class FriendServiceImpl( userId: Long, friendId: Long, ): DeleteFriendResponse { - TODO("Not yet implemented") + val user = userServiceImpl.getUser(userId) + val friend = userServiceImpl.getUser(friendId) + + val userFriendRelation = getFriendshipWithStatus(userId, friendId, FriendRequestStatus.ACCEPTED) + val friendFriendRelation = + getFriendshipWithStatus(friendId, userId, FriendRequestStatus.ACCEPTED) + + user.removeFriendRelation(userFriendRelation) + friend.removeFriendRelation(friendFriendRelation) + + friendRepository.delete(userFriendRelation) + friendRepository.delete(friendFriendRelation) + + return DeleteFriendResponse(friendId) } fun checkSelfFriend( @@ -92,6 +105,11 @@ class FriendServiceImpl( friendId: Long, requestStatus: FriendRequestStatus, ): Friend { + if (requestStatus == FriendRequestStatus.ACCEPTED) { + return friendRepository + .findByUserIdAndFriendIdAndRequestStatus(userId, friendId, requestStatus) + ?: throw ServiceException(UserErrorCode.FRIEND_NOT_FOUND) + } return friendRepository .findByUserIdAndFriendIdAndRequestStatus(userId, friendId, requestStatus) ?: throw ServiceException(UserErrorCode.FRIENDSHIP_ALREADY_EXISTS_OR_NOT_FOUND) From 5e7fd7c51640cccb2f1012ce7e64a0bae600fa26 Mon Sep 17 00:00:00 2001 From: minahYu Date: Thu, 20 Jun 2024 11:18:26 +0900 Subject: [PATCH 05/11] =?UTF-8?q?chore:=20deleteFriend=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=EC=97=90=20=EB=8C=80=ED=95=9C=20=EC=A3=BC?= =?UTF-8?q?=EC=84=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- user/src/main/kotlin/kpring/user/service/FriendService.kt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/user/src/main/kotlin/kpring/user/service/FriendService.kt b/user/src/main/kotlin/kpring/user/service/FriendService.kt index 6fd10a30..6f4214e7 100644 --- a/user/src/main/kotlin/kpring/user/service/FriendService.kt +++ b/user/src/main/kotlin/kpring/user/service/FriendService.kt @@ -46,6 +46,14 @@ interface FriendService { friendId: Long, ): AddFriendResponse + /*** + * 사용자가 친구와의 관계를 끊을 때 친구 상태를 삭제하는 메서드 + * + * @param userId : 로그인한 사용자 ID. + * @param friendId : 기존에 친구였지만 친구관계를 삭제하고자 하는 사용자 ID. + * @return 전에 친구였던 사용자의 ID를 담고 있는 DeleteFriendResponse 리턴 + * @throws FRIEND_NOT_FOUND : 친구 중에 friendId 를 가진 사용자가 없을 경우 발생하는 예외 + */ fun deleteFriend( userId: Long, friendId: Long, From 850a0c1041a563436bb59294aa756b924195248f Mon Sep 17 00:00:00 2001 From: minahYu Date: Thu, 20 Jun 2024 11:18:58 +0900 Subject: [PATCH 06/11] =?UTF-8?q?chore:=20deleteFriend=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=20=EA=B4=80=EB=A0=A8=20controller=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=EC=BD=94=EB=93=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../user/controller/FriendControllerTest.kt | 154 +++++++++++++++++- 1 file changed, 150 insertions(+), 4 deletions(-) diff --git a/user/src/test/kotlin/kpring/user/controller/FriendControllerTest.kt b/user/src/test/kotlin/kpring/user/controller/FriendControllerTest.kt index 53867dc6..84e07818 100644 --- a/user/src/test/kotlin/kpring/user/controller/FriendControllerTest.kt +++ b/user/src/test/kotlin/kpring/user/controller/FriendControllerTest.kt @@ -13,10 +13,7 @@ import kpring.core.global.exception.ServiceException import kpring.test.restdoc.dsl.restDoc import kpring.test.restdoc.json.JsonDataType import kpring.test.restdoc.json.JsonDataType.Strings -import kpring.user.dto.response.AddFriendResponse -import kpring.user.dto.response.FailMessageResponse -import kpring.user.dto.response.GetFriendRequestResponse -import kpring.user.dto.response.GetFriendRequestsResponse +import kpring.user.dto.response.* import kpring.user.exception.UserErrorCode import kpring.user.global.AuthValidator import kpring.user.global.CommonTest @@ -492,5 +489,154 @@ internal class FriendControllerTest( } } } + + describe("친구삭제 API") { + it("친구삭제 성공") { + // given + val data = DeleteFriendResponse(friendId = CommonTest.TEST_FRIEND_ID) + + val response = ApiResponse(data = data) + every { authClient.getTokenInfo(any()) }.returns( + ApiResponse(data = TokenInfo(TokenType.ACCESS, CommonTest.TEST_USER_ID.toString())), + ) + every { authValidator.checkIfAccessTokenAndGetUserId(any()) } returns CommonTest.TEST_USER_ID.toString() + every { authValidator.checkIfUserIsSelf(any(), any()) } returns Unit + every { + friendService.deleteFriend( + CommonTest.TEST_USER_ID, + CommonTest.TEST_FRIEND_ID, + ) + } returns data + + // when + val result = + webTestClient.delete() + .uri( + "/api/v1/user/{userId}/friend/{friendId}", + CommonTest.TEST_USER_ID, + CommonTest.TEST_FRIEND_ID, + ) + .header("Authorization", CommonTest.TEST_TOKEN) + .exchange() + + // then + val docsRoot = + result + .expectStatus().isOk + .expectBody().json(objectMapper.writeValueAsString(response)) + + // docs + docsRoot + .restDoc( + identifier = "deleteFriend200", + description = "친구삭제 API", + ) { + request { + path { + "userId" mean "사용자 아이디" + "friendId" mean "친구신청을 받은 사용자의 아이디" + } + header { + "Authorization" mean "Bearer token" + } + } + response { + body { + "data.friendId" type Strings mean "친구신청을 받은 사용자의 아이디" + } + } + } + } + it("친구삭제 실패 : 권한이 없는 토큰") { + // given + val response = + FailMessageResponse.builder().message(UserErrorCode.NOT_ALLOWED.message()).build() + every { authClient.getTokenInfo(any()) } throws ServiceException(UserErrorCode.NOT_ALLOWED) + + // when + val result = + webTestClient.delete() + .uri( + "/api/v1/user/{userId}/friend/{friendId}", + CommonTest.TEST_USER_ID, + CommonTest.TEST_FRIEND_ID, + ) + .header("Authorization", CommonTest.TEST_TOKEN) + .exchange() + + // then + val docsRoot = + result + .expectStatus().isForbidden + .expectBody().json(objectMapper.writeValueAsString(response)) + + // docs + docsRoot + .restDoc( + identifier = "deleteFriend403", + description = "친구삭제 API", + ) { + request { + path { + "userId" mean "사용자 아이디" + "friendId" mean "친구신청을 받은 사용자의 아이디" + } + header { + "Authorization" mean "Bearer token" + } + } + response { + body { + "message" type Strings mean "에러 메시지" + } + } + } + } + it("친구삭제 실패 : 서버 내부 오류") { + // given + val response = + FailMessageResponse.serverError + every { authClient.getTokenInfo(any()) } throws RuntimeException("서버 내부 오류") + + // when + val result = + webTestClient.delete() + .uri( + "/api/v1/user/{userId}/friend/{friendId}", + CommonTest.TEST_USER_ID, + CommonTest.TEST_FRIEND_ID, + ) + .header("Authorization", CommonTest.TEST_TOKEN) + .exchange() + + // then + val docsRoot = + result + .expectStatus().isEqualTo(500) + .expectBody().json(objectMapper.writeValueAsString(response)) + + // docs + docsRoot + .restDoc( + identifier = "deleteFriend500", + description = "친구삭제 API", + ) { + request { + path { + "userId" mean "사용자 아이디" + "friendId" mean "친구신청을 받은 사용자의 아이디" + } + header { + "Authorization" mean "Bearer token" + } + } + response { + body { + "message" type Strings mean "에러 메시지" + } + } + } + } + } } }) From c21abf9f33ab8ae708e4a8c8d778dc4a03c4c939 Mon Sep 17 00:00:00 2001 From: minahYu Date: Thu, 20 Jun 2024 11:19:14 +0900 Subject: [PATCH 07/11] =?UTF-8?q?chore:=20deleteFriend=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=20=EA=B4=80=EB=A0=A8=20service=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../user/service/FriendServiceImplTest.kt | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/user/src/test/kotlin/kpring/user/service/FriendServiceImplTest.kt b/user/src/test/kotlin/kpring/user/service/FriendServiceImplTest.kt index 4b174825..23c6ffd9 100644 --- a/user/src/test/kotlin/kpring/user/service/FriendServiceImplTest.kt +++ b/user/src/test/kotlin/kpring/user/service/FriendServiceImplTest.kt @@ -190,4 +190,67 @@ internal class FriendServiceImplTest : FunSpec({ } exception.errorCode.message() shouldBe "해당하는 친구신청이 없거나 이미 친구입니다." } + + test("친구삭제_성공") { + val user = mockk(relaxed = true) + val friend = mockk(relaxed = true) + val userFriendRelation = mockk(relaxed = true) + val friendFriendRelation = mockk(relaxed = true) + + every { userService.getUser(CommonTest.TEST_USER_ID) } returns user + every { userService.getUser(CommonTest.TEST_FRIEND_ID) } returns friend + + every { + friendRepository.findByUserIdAndFriendIdAndRequestStatus( + CommonTest.TEST_USER_ID, + CommonTest.TEST_FRIEND_ID, + FriendRequestStatus.ACCEPTED, + ) + } returns userFriendRelation + every { + friendRepository.findByUserIdAndFriendIdAndRequestStatus( + CommonTest.TEST_FRIEND_ID, + CommonTest.TEST_USER_ID, + FriendRequestStatus.ACCEPTED, + ) + } returns friendFriendRelation + + every { friendRepository.delete(any()) } just Runs + + val response = + friendService.deleteFriend(CommonTest.TEST_USER_ID, CommonTest.TEST_FRIEND_ID) +// response.friendId shouldBe CommonTest.TEST_FRIEND_ID + + verify { user.removeFriendRelation(userFriendRelation) } + verify { friend.removeFriendRelation(friendFriendRelation) } + verify(exactly = 2) { friendRepository.delete(any()) } + } + + test("친구삭제_실패_해당하는 친구가 없는 케이스") { + val user = mockk(relaxed = true) + val friend = mockk(relaxed = true) + + every { userService.getUser(CommonTest.TEST_USER_ID) } returns user + every { userService.getUser(CommonTest.TEST_FRIEND_ID) } returns friend + every { + friendRepository.findByUserIdAndFriendIdAndRequestStatus( + CommonTest.TEST_USER_ID, + CommonTest.TEST_FRIEND_ID, + FriendRequestStatus.ACCEPTED, + ) + } throws ServiceException(UserErrorCode.FRIEND_NOT_FOUND) + every { + friendRepository.findByUserIdAndFriendIdAndRequestStatus( + CommonTest.TEST_FRIEND_ID, + CommonTest.TEST_USER_ID, + FriendRequestStatus.ACCEPTED, + ) + } throws ServiceException(UserErrorCode.FRIEND_NOT_FOUND) + + val exception = + shouldThrow { + friendService.deleteFriend(CommonTest.TEST_USER_ID, CommonTest.TEST_FRIEND_ID) + } + exception.errorCode.message() shouldBe "해당하는 친구가 없습니다." + } }) From 9ab49ca25aa8de5138109ec1683db558b181b5f6 Mon Sep 17 00:00:00 2001 From: minahYu Date: Sat, 22 Jun 2024 14:59:23 +0900 Subject: [PATCH 08/11] =?UTF-8?q?refac:=20cascade=20=ED=86=B5=ED=95=B4=20?= =?UTF-8?q?=EC=B9=9C=EA=B5=AC=20=EC=97=B0=EA=B4=80=EA=B4=80=EA=B3=84?= =?UTF-8?q?=EB=A5=BC=20=EC=82=AD=EC=A0=9C=ED=95=98=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- user/src/main/kotlin/kpring/user/entity/User.kt | 7 ++++++- .../main/kotlin/kpring/user/service/FriendServiceImpl.kt | 9 +-------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/user/src/main/kotlin/kpring/user/entity/User.kt b/user/src/main/kotlin/kpring/user/entity/User.kt index 076254a3..4f97a7ff 100644 --- a/user/src/main/kotlin/kpring/user/entity/User.kt +++ b/user/src/main/kotlin/kpring/user/entity/User.kt @@ -16,7 +16,12 @@ class User( @Column(nullable = false) var password: String, var file: String?, - @OneToMany(fetch = FetchType.LAZY, mappedBy = "user", cascade = [CascadeType.ALL]) + @OneToMany( + fetch = FetchType.LAZY, + mappedBy = "user", + cascade = [CascadeType.ALL], + orphanRemoval = true, + ) val friends: MutableSet = mutableSetOf(), // Other fields and methods... ) { diff --git a/user/src/main/kotlin/kpring/user/service/FriendServiceImpl.kt b/user/src/main/kotlin/kpring/user/service/FriendServiceImpl.kt index 9ccbd4dc..e8e4d72d 100644 --- a/user/src/main/kotlin/kpring/user/service/FriendServiceImpl.kt +++ b/user/src/main/kotlin/kpring/user/service/FriendServiceImpl.kt @@ -67,17 +67,10 @@ class FriendServiceImpl( friendId: Long, ): DeleteFriendResponse { val user = userServiceImpl.getUser(userId) - val friend = userServiceImpl.getUser(friendId) + userServiceImpl.getUser(friendId) val userFriendRelation = getFriendshipWithStatus(userId, friendId, FriendRequestStatus.ACCEPTED) - val friendFriendRelation = - getFriendshipWithStatus(friendId, userId, FriendRequestStatus.ACCEPTED) - user.removeFriendRelation(userFriendRelation) - friend.removeFriendRelation(friendFriendRelation) - - friendRepository.delete(userFriendRelation) - friendRepository.delete(friendFriendRelation) return DeleteFriendResponse(friendId) } From 9ce8e5855850788e9170b928cb2942a9a74ecca8 Mon Sep 17 00:00:00 2001 From: minahYu Date: Sat, 22 Jun 2024 15:02:36 +0900 Subject: [PATCH 09/11] =?UTF-8?q?test:=20=EB=AA=85=EC=8B=9C=EC=A0=81?= =?UTF-8?q?=EC=9D=B8=20=EC=BD=94=EB=93=9C=EB=A5=BC=20=EC=9C=84=ED=95=B4=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=EC=BD=94=EB=93=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../user/service/FriendServiceImplTest.kt | 66 ++++++++----------- 1 file changed, 28 insertions(+), 38 deletions(-) diff --git a/user/src/test/kotlin/kpring/user/service/FriendServiceImplTest.kt b/user/src/test/kotlin/kpring/user/service/FriendServiceImplTest.kt index 23c6ffd9..ffe15714 100644 --- a/user/src/test/kotlin/kpring/user/service/FriendServiceImplTest.kt +++ b/user/src/test/kotlin/kpring/user/service/FriendServiceImplTest.kt @@ -34,8 +34,8 @@ internal class FriendServiceImplTest : FunSpec({ ) test("친구신청_성공") { - val user = mockk(relaxed = true) - val friend = mockk(relaxed = true) + val user = mockk { every { id } returns CommonTest.TEST_USER_ID } + val friend = mockk { every { id } returns CommonTest.TEST_FRIEND_ID } every { userService.getUser(CommonTest.TEST_USER_ID) } returns user every { userService.getUser(CommonTest.TEST_FRIEND_ID) } returns friend @@ -47,7 +47,7 @@ internal class FriendServiceImplTest : FunSpec({ every { friend.receiveFriendRequest(user) } just Runs val response = friendService.addFriend(CommonTest.TEST_USER_ID, CommonTest.TEST_FRIEND_ID) - response.friendId shouldBe friend.id + response.friendId shouldBe CommonTest.TEST_FRIEND_ID verify { friendService.checkSelfFriend(user, friend) } verify { @@ -56,7 +56,7 @@ internal class FriendServiceImplTest : FunSpec({ } test("친구신청_실패_자기자신을 친구로 추가하는 케이스") { - val user = mockk(relaxed = true) + val user = mockk() every { userService.getUser(CommonTest.TEST_USER_ID) } returns user every { @@ -77,8 +77,8 @@ internal class FriendServiceImplTest : FunSpec({ } test("친구신청_실패_이미 친구인 케이스") { - val user = mockk(relaxed = true) - val friend = mockk(relaxed = true) + val user = mockk() + val friend = mockk() every { userService.getUser(CommonTest.TEST_USER_ID) } returns user every { userService.getUser(CommonTest.TEST_FRIEND_ID) } returns friend @@ -103,9 +103,17 @@ internal class FriendServiceImplTest : FunSpec({ } test("친구신청조회_성공") { - val friend = mockk(relaxed = true) - val friendList = listOf(mockk(relaxed = true)) + val friendInfo = + mockk { + every { id } returns CommonTest.TEST_FRIEND_ID + every { username } returns CommonTest.TEST_FRIEND_USERNAME + } + val friend = + mockk { + every { friend } returns friendInfo + } + val friendList = listOf(friend) every { friendRepository.findAllByUserIdAndRequestStatus( CommonTest.TEST_USER_ID, @@ -114,15 +122,16 @@ internal class FriendServiceImplTest : FunSpec({ } returns friendList val response = friendService.getFriendRequests(CommonTest.TEST_USER_ID) + response.userId shouldBe CommonTest.TEST_USER_ID for (request in response.friendRequests) { - request.friendId shouldBe friend.id - request.username shouldBe friend.username + request.friendId shouldBe CommonTest.TEST_FRIEND_ID + request.username shouldBe CommonTest.TEST_FRIEND_USERNAME } } test("친구신청수락_성공") { - val receivedFriend = mockk(relaxed = true) - val requestedFriend = mockk(relaxed = true) + val receivedFriend = mockk() + val requestedFriend = mockk() every { friendRepository.findByUserIdAndFriendIdAndRequestStatus( @@ -192,10 +201,9 @@ internal class FriendServiceImplTest : FunSpec({ } test("친구삭제_성공") { - val user = mockk(relaxed = true) - val friend = mockk(relaxed = true) - val userFriendRelation = mockk(relaxed = true) - val friendFriendRelation = mockk(relaxed = true) + val user = mockk() + val friend = mockk() + val userFriendRelation = mockk() every { userService.getUser(CommonTest.TEST_USER_ID) } returns user every { userService.getUser(CommonTest.TEST_FRIEND_ID) } returns friend @@ -207,28 +215,17 @@ internal class FriendServiceImplTest : FunSpec({ FriendRequestStatus.ACCEPTED, ) } returns userFriendRelation - every { - friendRepository.findByUserIdAndFriendIdAndRequestStatus( - CommonTest.TEST_FRIEND_ID, - CommonTest.TEST_USER_ID, - FriendRequestStatus.ACCEPTED, - ) - } returns friendFriendRelation - every { friendRepository.delete(any()) } just Runs + every { user.removeFriendRelation(userFriendRelation) } just Runs val response = friendService.deleteFriend(CommonTest.TEST_USER_ID, CommonTest.TEST_FRIEND_ID) -// response.friendId shouldBe CommonTest.TEST_FRIEND_ID - - verify { user.removeFriendRelation(userFriendRelation) } - verify { friend.removeFriendRelation(friendFriendRelation) } - verify(exactly = 2) { friendRepository.delete(any()) } + response.friendId shouldBe CommonTest.TEST_FRIEND_ID } test("친구삭제_실패_해당하는 친구가 없는 케이스") { - val user = mockk(relaxed = true) - val friend = mockk(relaxed = true) + val user = mockk() + val friend = mockk() every { userService.getUser(CommonTest.TEST_USER_ID) } returns user every { userService.getUser(CommonTest.TEST_FRIEND_ID) } returns friend @@ -239,13 +236,6 @@ internal class FriendServiceImplTest : FunSpec({ FriendRequestStatus.ACCEPTED, ) } throws ServiceException(UserErrorCode.FRIEND_NOT_FOUND) - every { - friendRepository.findByUserIdAndFriendIdAndRequestStatus( - CommonTest.TEST_FRIEND_ID, - CommonTest.TEST_USER_ID, - FriendRequestStatus.ACCEPTED, - ) - } throws ServiceException(UserErrorCode.FRIEND_NOT_FOUND) val exception = shouldThrow { From b9b246d456b5c4d1e6b872d4af376acca0804241 Mon Sep 17 00:00:00 2001 From: minahYu Date: Mon, 24 Jun 2024 17:41:59 +0900 Subject: [PATCH 10/11] =?UTF-8?q?refac:=20friendship=20=EA=B0=80=EC=A0=B8?= =?UTF-8?q?=EC=98=A4=EB=8A=94=20=EC=BD=94=EB=93=9C=EC=97=90=20=EB=8C=80?= =?UTF-8?q?=ED=95=9C=20=EC=B1=85=EC=9E=84=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kpring/user/exception/UserErrorCode.kt | 11 +++-- .../user/repository/FriendRepository.kt | 5 +++ .../kpring/user/service/FriendServiceImpl.kt | 41 ++++++++++++++----- 3 files changed, 40 insertions(+), 17 deletions(-) diff --git a/user/src/main/kotlin/kpring/user/exception/UserErrorCode.kt b/user/src/main/kotlin/kpring/user/exception/UserErrorCode.kt index a4450bcc..a26fa30f 100644 --- a/user/src/main/kotlin/kpring/user/exception/UserErrorCode.kt +++ b/user/src/main/kotlin/kpring/user/exception/UserErrorCode.kt @@ -19,12 +19,11 @@ enum class UserErrorCode( ALREADY_FRIEND(HttpStatus.BAD_REQUEST, "4030", "이미 친구입니다."), NOT_SELF_FOLLOW(HttpStatus.BAD_REQUEST, "4031", "자기자신에게 친구요청을 보낼 수 없습니다"), - FRIENDSHIP_ALREADY_EXISTS_OR_NOT_FOUND( - HttpStatus.BAD_REQUEST, - "4032", - "해당하는 친구신청이 없거나 이미 친구입니다.", - ), - FRIEND_NOT_FOUND(HttpStatus.BAD_REQUEST, "4033", "해당하는 친구가 없습니다."), + + FRIENDSHIP_ALREADY_EXISTS(HttpStatus.BAD_REQUEST, "4032", "이미 친구입니다."), + FRIENDSHIP_NOT_FOUND(HttpStatus.NOT_FOUND, "4033", "해당하는 친구신청이 없습니다."), + + FRIEND_NOT_FOUND(HttpStatus.NOT_FOUND, "4034", "해당하는 친구가 없습니다."), ; override fun message(): String = this.message diff --git a/user/src/main/kotlin/kpring/user/repository/FriendRepository.kt b/user/src/main/kotlin/kpring/user/repository/FriendRepository.kt index eadac275..66e8ceb7 100644 --- a/user/src/main/kotlin/kpring/user/repository/FriendRepository.kt +++ b/user/src/main/kotlin/kpring/user/repository/FriendRepository.kt @@ -20,4 +20,9 @@ interface FriendRepository : JpaRepository { friendId: Long, requestStatus: FriendRequestStatus, ): Friend? + + fun findByUserIdAndFriendId( + userId: Long, + friendId: Long, + ): Friend? } diff --git a/user/src/main/kotlin/kpring/user/service/FriendServiceImpl.kt b/user/src/main/kotlin/kpring/user/service/FriendServiceImpl.kt index e8e4d72d..27f16cf4 100644 --- a/user/src/main/kotlin/kpring/user/service/FriendServiceImpl.kt +++ b/user/src/main/kotlin/kpring/user/service/FriendServiceImpl.kt @@ -53,8 +53,8 @@ class FriendServiceImpl( userId: Long, friendId: Long, ): AddFriendResponse { - val receivedFriend = getFriendshipWithStatus(userId, friendId, FriendRequestStatus.RECEIVED) - val requestedFriend = getFriendshipWithStatus(friendId, userId, FriendRequestStatus.REQUESTED) + val receivedFriend = getPendingFriendship(userId, friendId) + val requestedFriend = getPendingFriendship(friendId, userId) receivedFriend.updateRequestStatus(FriendRequestStatus.ACCEPTED) requestedFriend.updateRequestStatus(FriendRequestStatus.ACCEPTED) @@ -69,7 +69,7 @@ class FriendServiceImpl( val user = userServiceImpl.getUser(userId) userServiceImpl.getUser(friendId) - val userFriendRelation = getFriendshipWithStatus(userId, friendId, FriendRequestStatus.ACCEPTED) + val userFriendRelation = findAcceptedFriendship(userId, friendId) user.removeFriendRelation(userFriendRelation) return DeleteFriendResponse(friendId) @@ -93,18 +93,37 @@ class FriendServiceImpl( } } - private fun getFriendshipWithStatus( + private fun findFriendship( userId: Long, friendId: Long, - requestStatus: FriendRequestStatus, ): Friend { - if (requestStatus == FriendRequestStatus.ACCEPTED) { - return friendRepository - .findByUserIdAndFriendIdAndRequestStatus(userId, friendId, requestStatus) - ?: throw ServiceException(UserErrorCode.FRIEND_NOT_FOUND) + val friendship = + friendRepository.findByUserIdAndFriendId(userId, friendId) + ?: throw ServiceException(UserErrorCode.FRIENDSHIP_NOT_FOUND) + return friendship + } + + private fun checkNotAcceptedFriendship(friendship: Friend) { + if (friendship.requestStatus == FriendRequestStatus.ACCEPTED) { + throw ServiceException(UserErrorCode.FRIENDSHIP_ALREADY_EXISTS) } + } + + private fun getPendingFriendship( + userId: Long, + friendId: Long, + ): Friend { + val friendship = findFriendship(userId, friendId) + checkNotAcceptedFriendship(friendship) + return friendship + } + + private fun findAcceptedFriendship( + userId: Long, + friendId: Long, + ): Friend { return friendRepository - .findByUserIdAndFriendIdAndRequestStatus(userId, friendId, requestStatus) - ?: throw ServiceException(UserErrorCode.FRIENDSHIP_ALREADY_EXISTS_OR_NOT_FOUND) + .findByUserIdAndFriendIdAndRequestStatus(userId, friendId, FriendRequestStatus.ACCEPTED) + ?: throw ServiceException(UserErrorCode.FRIEND_NOT_FOUND) } } From 2b6c7cf1768b4d6f8b8c496ab03ec293408ef058 Mon Sep 17 00:00:00 2001 From: minahYu Date: Mon, 24 Jun 2024 17:44:30 +0900 Subject: [PATCH 11/11] =?UTF-8?q?test:=20=EC=84=9C=EB=B9=84=EC=8A=A4?= =?UTF-8?q?=EB=8B=A8=20=EC=BD=94=EB=93=9C=20=EC=88=98=EC=A0=95=EC=97=90=20?= =?UTF-8?q?=EB=94=B0=EB=A5=B8=20=ED=85=8C=EC=8A=A4=ED=8A=B8=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../user/service/FriendServiceImplTest.kt | 37 ++++++++++--------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/user/src/test/kotlin/kpring/user/service/FriendServiceImplTest.kt b/user/src/test/kotlin/kpring/user/service/FriendServiceImplTest.kt index ffe15714..cf195e4f 100644 --- a/user/src/test/kotlin/kpring/user/service/FriendServiceImplTest.kt +++ b/user/src/test/kotlin/kpring/user/service/FriendServiceImplTest.kt @@ -130,21 +130,25 @@ internal class FriendServiceImplTest : FunSpec({ } test("친구신청수락_성공") { - val receivedFriend = mockk() - val requestedFriend = mockk() + val receivedFriend = + mockk { + every { requestStatus } returns FriendRequestStatus.RECEIVED + } + val requestedFriend = + mockk { + every { requestStatus } returns FriendRequestStatus.REQUESTED + } every { - friendRepository.findByUserIdAndFriendIdAndRequestStatus( + friendRepository.findByUserIdAndFriendId( CommonTest.TEST_USER_ID, CommonTest.TEST_FRIEND_ID, - FriendRequestStatus.RECEIVED, ) } returns receivedFriend every { - friendRepository.findByUserIdAndFriendIdAndRequestStatus( + friendRepository.findByUserIdAndFriendId( CommonTest.TEST_FRIEND_ID, CommonTest.TEST_USER_ID, - FriendRequestStatus.REQUESTED, ) } returns requestedFriend @@ -156,48 +160,45 @@ internal class FriendServiceImplTest : FunSpec({ response.friendId shouldBe CommonTest.TEST_FRIEND_ID verify(exactly = 2) { - friendRepository.findByUserIdAndFriendIdAndRequestStatus(any(), any(), any()) + friendRepository.findByUserIdAndFriendId(any(), any()) } } test("친구신청수락_실패_해당하는 친구신청이 없는 케이스") { every { - friendRepository.findByUserIdAndFriendIdAndRequestStatus( + friendRepository.findByUserIdAndFriendId( CommonTest.TEST_USER_ID, CommonTest.TEST_FRIEND_ID, - FriendRequestStatus.RECEIVED, ) - } throws ServiceException(UserErrorCode.FRIENDSHIP_ALREADY_EXISTS_OR_NOT_FOUND) + } throws ServiceException(UserErrorCode.FRIENDSHIP_NOT_FOUND) val exception = shouldThrow { friendService.acceptFriendRequest(CommonTest.TEST_USER_ID, CommonTest.TEST_FRIEND_ID) } - exception.errorCode.message() shouldBe "해당하는 친구신청이 없거나 이미 친구입니다." + exception.errorCode.message() shouldBe "해당하는 친구신청이 없습니다." } test("친구신청수락_실패_이미 친구인 케이스") { every { - friendRepository.findByUserIdAndFriendIdAndRequestStatus( + friendRepository.findByUserIdAndFriendId( CommonTest.TEST_USER_ID, CommonTest.TEST_FRIEND_ID, - FriendRequestStatus.RECEIVED, ) - } throws ServiceException(UserErrorCode.FRIENDSHIP_ALREADY_EXISTS_OR_NOT_FOUND) + } throws ServiceException(UserErrorCode.FRIENDSHIP_ALREADY_EXISTS) every { - friendRepository.findByUserIdAndFriendIdAndRequestStatus( + friendRepository.findByUserIdAndFriendId( CommonTest.TEST_FRIEND_ID, CommonTest.TEST_USER_ID, - FriendRequestStatus.REQUESTED, ) - } throws ServiceException(UserErrorCode.FRIENDSHIP_ALREADY_EXISTS_OR_NOT_FOUND) + } throws ServiceException(UserErrorCode.FRIENDSHIP_ALREADY_EXISTS) val exception = shouldThrow { friendService.acceptFriendRequest(CommonTest.TEST_USER_ID, CommonTest.TEST_FRIEND_ID) } - exception.errorCode.message() shouldBe "해당하는 친구신청이 없거나 이미 친구입니다." + exception.errorCode.message() shouldBe "이미 친구입니다." } test("친구삭제_성공") {