From 532df89729092fdf4e4e905e9a58386decd84216 Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Fri, 1 Aug 2025 06:02:49 +0900 Subject: [PATCH 1/9] =?UTF-8?q?refactor:=20=EB=B3=80=EA=B2=BD=EB=90=9C=20a?= =?UTF-8?q?pi=20=EB=AA=85=EC=84=B8=EC=97=90=20=EB=A7=9E=EA=B2=8C=20?= =?UTF-8?q?=EC=BB=A8=ED=8A=B8=EB=A1=A4=EB=9F=AC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MentoringForMenteeController.java | 72 +++++++++++++++++++ ...java => MentoringForMentorController.java} | 57 +++++++-------- .../mentor/dto/CheckMentoringRequest.java | 9 +++ .../mentor/dto/CheckedMentoringsResponse.java | 15 ++++ 4 files changed, 123 insertions(+), 30 deletions(-) create mode 100644 src/main/java/com/example/solidconnection/mentor/controller/MentoringForMenteeController.java rename src/main/java/com/example/solidconnection/mentor/controller/{MentoringController.java => MentoringForMentorController.java} (59%) create mode 100644 src/main/java/com/example/solidconnection/mentor/dto/CheckMentoringRequest.java create mode 100644 src/main/java/com/example/solidconnection/mentor/dto/CheckedMentoringsResponse.java diff --git a/src/main/java/com/example/solidconnection/mentor/controller/MentoringForMenteeController.java b/src/main/java/com/example/solidconnection/mentor/controller/MentoringForMenteeController.java new file mode 100644 index 000000000..7c84ee282 --- /dev/null +++ b/src/main/java/com/example/solidconnection/mentor/controller/MentoringForMenteeController.java @@ -0,0 +1,72 @@ +package com.example.solidconnection.mentor.controller; + +import com.example.solidconnection.common.VerifyStatus; +import com.example.solidconnection.common.dto.SliceResponse; +import com.example.solidconnection.common.resolver.AuthorizedUser; +import com.example.solidconnection.mentor.dto.CheckMentoringRequest; +import com.example.solidconnection.mentor.dto.CheckedMentoringsResponse; +import com.example.solidconnection.mentor.dto.MentoringApplyRequest; +import com.example.solidconnection.mentor.dto.MentoringApplyResponse; +import com.example.solidconnection.mentor.dto.MentoringResponse; +import com.example.solidconnection.mentor.service.MentoringCommandService; +import com.example.solidconnection.mentor.service.MentoringQueryService; +import com.example.solidconnection.security.annotation.RequireRoleAccess; +import com.example.solidconnection.siteuser.domain.Role; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.data.web.PageableDefault; +import org.springframework.data.web.SortDefault; +import org.springframework.data.web.SortDefault.SortDefaults; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/mentee/mentorings") +public class MentoringForMenteeController { + + private final MentoringCommandService mentoringCommandService; + private final MentoringQueryService mentoringQueryService; + + @RequireRoleAccess(roles = Role.MENTEE) + @PostMapping + public ResponseEntity applyMentoring( + @AuthorizedUser long siteUserId, + @Valid @RequestBody MentoringApplyRequest mentoringApplyRequest + ) { + MentoringApplyResponse response = mentoringCommandService.applyMentoring(siteUserId, mentoringApplyRequest); + return ResponseEntity.ok(response); + } + + @RequireRoleAccess(roles = Role.MENTEE) + @GetMapping + public ResponseEntity> getMentorings( + @AuthorizedUser long siteUserId, + @RequestParam("verify-status") VerifyStatus verifyStatus, + @PageableDefault(size = 3) + @SortDefaults({ + @SortDefault(sort = "createdAt", direction = Sort.Direction.DESC), + @SortDefault(sort = "id", direction = Sort.Direction.DESC) + }) + Pageable pageable + ) { + return ResponseEntity.ok().build(); + } + + @RequireRoleAccess(roles = {Role.MENTEE}) + @PatchMapping("/check") + public ResponseEntity checkMentorings( + @AuthorizedUser long siteUserId, + @Valid @RequestBody CheckMentoringRequest checkMentoringRequest + ) { + return ResponseEntity.ok().build(); + } +} diff --git a/src/main/java/com/example/solidconnection/mentor/controller/MentoringController.java b/src/main/java/com/example/solidconnection/mentor/controller/MentoringForMentorController.java similarity index 59% rename from src/main/java/com/example/solidconnection/mentor/controller/MentoringController.java rename to src/main/java/com/example/solidconnection/mentor/controller/MentoringForMentorController.java index 5a347f3fb..8813a974f 100644 --- a/src/main/java/com/example/solidconnection/mentor/controller/MentoringController.java +++ b/src/main/java/com/example/solidconnection/mentor/controller/MentoringForMentorController.java @@ -1,57 +1,56 @@ package com.example.solidconnection.mentor.controller; +import com.example.solidconnection.common.dto.SliceResponse; import com.example.solidconnection.common.resolver.AuthorizedUser; -import com.example.solidconnection.mentor.dto.MentoringApplyRequest; -import com.example.solidconnection.mentor.dto.MentoringApplyResponse; -import com.example.solidconnection.mentor.dto.MentoringCheckResponse; +import com.example.solidconnection.mentor.dto.CheckMentoringRequest; +import com.example.solidconnection.mentor.dto.CheckedMentoringsResponse; import com.example.solidconnection.mentor.dto.MentoringConfirmRequest; import com.example.solidconnection.mentor.dto.MentoringConfirmResponse; import com.example.solidconnection.mentor.dto.MentoringCountResponse; -import com.example.solidconnection.mentor.dto.MentoringListResponse; +import com.example.solidconnection.mentor.dto.MentoringResponse; import com.example.solidconnection.mentor.service.MentoringCommandService; import com.example.solidconnection.mentor.service.MentoringQueryService; import com.example.solidconnection.security.annotation.RequireRoleAccess; import com.example.solidconnection.siteuser.domain.Role; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.data.web.PageableDefault; +import org.springframework.data.web.SortDefault; +import org.springframework.data.web.SortDefault.SortDefaults; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PatchMapping; import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequiredArgsConstructor -@RequestMapping("/mentorings") -public class MentoringController { +@RequestMapping("/mentor/mentorings") +public class MentoringForMentorController { private final MentoringCommandService mentoringCommandService; private final MentoringQueryService mentoringQueryService; - @RequireRoleAccess(roles = Role.MENTEE) - @PostMapping("/apply") - public ResponseEntity applyMentoring( - @AuthorizedUser long siteUserId, - @Valid @RequestBody MentoringApplyRequest mentoringApplyRequest - ) { - MentoringApplyResponse response = mentoringCommandService.applyMentoring(siteUserId, mentoringApplyRequest); - return ResponseEntity.ok(response); - } - @RequireRoleAccess(roles = {Role.ADMIN, Role.MENTOR}) - @GetMapping("/apply") - public ResponseEntity getMentorings( - @AuthorizedUser long siteUserId + @GetMapping + public ResponseEntity> getMentorings( + @AuthorizedUser long siteUserId, + @PageableDefault(size = 3) + @SortDefaults({ + @SortDefault(sort = "createdAt", direction = Sort.Direction.DESC), + @SortDefault(sort = "id", direction = Sort.Direction.DESC) + }) + Pageable pageable ) { - MentoringListResponse responses = mentoringQueryService.getMentorings(siteUserId); - return ResponseEntity.ok(responses); + return ResponseEntity.ok().build(); } @RequireRoleAccess(roles = {Role.ADMIN, Role.MENTOR}) - @PatchMapping("/{mentoring-id}/apply") + @PatchMapping("/{mentoring-id}") public ResponseEntity confirmMentoring( @AuthorizedUser long siteUserId, @PathVariable("mentoring-id") Long mentoringId, @@ -62,13 +61,12 @@ public ResponseEntity confirmMentoring( } @RequireRoleAccess(roles = {Role.ADMIN, Role.MENTOR}) - @PatchMapping("/{mentoring-id}/check") - public ResponseEntity checkMentoring( + @PatchMapping("/check") + public ResponseEntity checkMentoring( @AuthorizedUser long siteUserId, - @PathVariable("mentoring-id") Long mentoringId + @RequestBody CheckMentoringRequest mentoringCheckRequest ) { - MentoringCheckResponse response = mentoringCommandService.checkMentoring(siteUserId, mentoringId); - return ResponseEntity.ok(response); + return ResponseEntity.ok().build(); } @RequireRoleAccess(roles = {Role.ADMIN, Role.MENTOR}) @@ -76,7 +74,6 @@ public ResponseEntity checkMentoring( public ResponseEntity getUncheckedMentoringsCount( @AuthorizedUser long siteUserId ) { - MentoringCountResponse response = mentoringQueryService.getNewMentoringsCount(siteUserId); - return ResponseEntity.ok(response); + return ResponseEntity.ok().build(); } } diff --git a/src/main/java/com/example/solidconnection/mentor/dto/CheckMentoringRequest.java b/src/main/java/com/example/solidconnection/mentor/dto/CheckMentoringRequest.java new file mode 100644 index 000000000..ebd3bacf1 --- /dev/null +++ b/src/main/java/com/example/solidconnection/mentor/dto/CheckMentoringRequest.java @@ -0,0 +1,9 @@ +package com.example.solidconnection.mentor.dto; + +import java.util.List; + +public record CheckMentoringRequest( + List checkedMentoringIds +) { + +} diff --git a/src/main/java/com/example/solidconnection/mentor/dto/CheckedMentoringsResponse.java b/src/main/java/com/example/solidconnection/mentor/dto/CheckedMentoringsResponse.java new file mode 100644 index 000000000..2b286543a --- /dev/null +++ b/src/main/java/com/example/solidconnection/mentor/dto/CheckedMentoringsResponse.java @@ -0,0 +1,15 @@ +package com.example.solidconnection.mentor.dto; + +import com.example.solidconnection.mentor.domain.Mentoring; +import java.util.List; + +public record CheckedMentoringsResponse( + List checkedMentoringIds +) { + + public static CheckedMentoringsResponse from(List mentorings) { + return new CheckedMentoringsResponse( + mentorings.stream().map(Mentoring::getId).toList() + ); + } +} From 4175a9f2c764cabaf12071b9b933c7d81c8dd9e4 Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Fri, 1 Aug 2025 07:04:37 +0900 Subject: [PATCH 2/9] =?UTF-8?q?feat:=20=EB=A9=98=ED=86=A0=EB=A7=81=20?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D=20=EC=A1=B0=ED=9A=8C=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=EB=84=A4=EC=9D=B4=EC=85=98=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 추가로 N+1 해결 --- .../MentoringForMenteeController.java | 3 +- .../MentoringForMentorController.java | 3 +- .../mentor/dto/MentoringResponse.java | 6 +- .../repository/MentoringRepository.java | 11 +++- .../mentor/service/MentoringQueryService.java | 58 +++++++++++++++---- 5 files changed, 64 insertions(+), 17 deletions(-) diff --git a/src/main/java/com/example/solidconnection/mentor/controller/MentoringForMenteeController.java b/src/main/java/com/example/solidconnection/mentor/controller/MentoringForMenteeController.java index 7c84ee282..0fae22326 100644 --- a/src/main/java/com/example/solidconnection/mentor/controller/MentoringForMenteeController.java +++ b/src/main/java/com/example/solidconnection/mentor/controller/MentoringForMenteeController.java @@ -58,7 +58,8 @@ public ResponseEntity> getMentorings( }) Pageable pageable ) { - return ResponseEntity.ok().build(); + SliceResponse response = mentoringQueryService.getMentoringsForMentee(siteUserId, verifyStatus, pageable); + return ResponseEntity.ok(response); } @RequireRoleAccess(roles = {Role.MENTEE}) diff --git a/src/main/java/com/example/solidconnection/mentor/controller/MentoringForMentorController.java b/src/main/java/com/example/solidconnection/mentor/controller/MentoringForMentorController.java index 8813a974f..606f75759 100644 --- a/src/main/java/com/example/solidconnection/mentor/controller/MentoringForMentorController.java +++ b/src/main/java/com/example/solidconnection/mentor/controller/MentoringForMentorController.java @@ -46,7 +46,8 @@ public ResponseEntity> getMentorings( }) Pageable pageable ) { - return ResponseEntity.ok().build(); + SliceResponse response = mentoringQueryService.getMentoringsForMentor(siteUserId, pageable); + return ResponseEntity.ok(response); } @RequireRoleAccess(roles = {Role.ADMIN, Role.MENTOR}) diff --git a/src/main/java/com/example/solidconnection/mentor/dto/MentoringResponse.java b/src/main/java/com/example/solidconnection/mentor/dto/MentoringResponse.java index 6b96295ad..782538f2f 100644 --- a/src/main/java/com/example/solidconnection/mentor/dto/MentoringResponse.java +++ b/src/main/java/com/example/solidconnection/mentor/dto/MentoringResponse.java @@ -12,11 +12,11 @@ public record MentoringResponse( ZonedDateTime createdAt ) { - public static MentoringResponse from(Mentoring mentoring, SiteUser mentee) { + public static MentoringResponse from(Mentoring mentoring, SiteUser partner) { return new MentoringResponse( mentoring.getId(), - mentee.getProfileImageUrl(), - mentee.getNickname(), + partner.getProfileImageUrl(), + partner.getNickname(), mentoring.getCheckedAt() != null, mentoring.getCreatedAt() ); diff --git a/src/main/java/com/example/solidconnection/mentor/repository/MentoringRepository.java b/src/main/java/com/example/solidconnection/mentor/repository/MentoringRepository.java index 8f7cfade3..e3a5bd4cd 100644 --- a/src/main/java/com/example/solidconnection/mentor/repository/MentoringRepository.java +++ b/src/main/java/com/example/solidconnection/mentor/repository/MentoringRepository.java @@ -1,7 +1,10 @@ package com.example.solidconnection.mentor.repository; +import com.example.solidconnection.common.VerifyStatus; import com.example.solidconnection.mentor.domain.Mentoring; import java.util.List; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; @@ -12,7 +15,13 @@ public interface MentoringRepository extends JpaRepository { boolean existsByMentorIdAndMenteeId(long mentorId, long menteeId); - List findAllByMentorId(long mentorId); + Slice findAllByMentorId(long mentorId, Pageable pageable); + + @Query(""" + SELECT m FROM Mentoring m + WHERE m.menteeId = :menteeId AND m.verifyStatus = :verifyStatus + """) + Slice findAllByMenteeIdAndVerifyStatus(@Param("menteeId") long menteeId, @Param("verifyStatus") VerifyStatus verifyStatus, Pageable pageable); @Query(""" SELECT m FROM Mentoring m diff --git a/src/main/java/com/example/solidconnection/mentor/service/MentoringQueryService.java b/src/main/java/com/example/solidconnection/mentor/service/MentoringQueryService.java index 2ffa36602..b8ede796c 100644 --- a/src/main/java/com/example/solidconnection/mentor/service/MentoringQueryService.java +++ b/src/main/java/com/example/solidconnection/mentor/service/MentoringQueryService.java @@ -2,19 +2,25 @@ import static com.example.solidconnection.common.exception.ErrorCode.MENTOR_NOT_FOUND; +import com.example.solidconnection.common.VerifyStatus; +import com.example.solidconnection.common.dto.SliceResponse; import com.example.solidconnection.common.exception.CustomException; -import com.example.solidconnection.common.exception.ErrorCode; import com.example.solidconnection.mentor.domain.Mentor; import com.example.solidconnection.mentor.domain.Mentoring; import com.example.solidconnection.mentor.dto.MentoringCountResponse; -import com.example.solidconnection.mentor.dto.MentoringListResponse; import com.example.solidconnection.mentor.dto.MentoringResponse; import com.example.solidconnection.mentor.repository.MentorRepository; import com.example.solidconnection.mentor.repository.MentoringRepository; import com.example.solidconnection.siteuser.domain.SiteUser; import com.example.solidconnection.siteuser.repository.SiteUserRepository; +import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -27,21 +33,51 @@ public class MentoringQueryService { private final SiteUserRepository siteUserRepository; @Transactional(readOnly = true) - public MentoringListResponse getMentorings(long siteUserId) { + public SliceResponse getMentoringsForMentee( + long siteUserId, VerifyStatus verifyStatus, Pageable pageable + ) { + Slice mentoringSlice = mentoringRepository.findAllByMenteeIdAndVerifyStatus(siteUserId, verifyStatus, pageable); + + List content = buildMentoringResponsesWithBatchQuery( + mentoringSlice.toList(), + Mentoring::getMentorId + ); + + return SliceResponse.of(content, mentoringSlice); + } + + @Transactional(readOnly = true) + public SliceResponse getMentoringsForMentor(long siteUserId, Pageable pageable) { Mentor mentor = mentorRepository.findBySiteUserId(siteUserId) .orElseThrow(() -> new CustomException(MENTOR_NOT_FOUND)); + Slice mentoringSlice = mentoringRepository.findAllByMentorId(mentor.getId(), pageable); + + List content = buildMentoringResponsesWithBatchQuery( + mentoringSlice.toList(), + Mentoring::getMenteeId + ); - List mentorings = mentoringRepository.findAllByMentorId(mentor.getId()); - List mentoringResponses = mentorings.stream() - .map(mentoring -> { - SiteUser mentee = siteUserRepository.findById(mentoring.getMenteeId()) - .orElseThrow(() -> new CustomException(ErrorCode.USER_NOT_FOUND)); + return SliceResponse.of(content, mentoringSlice); + } - return MentoringResponse.from(mentoring, mentee); - }) + private List buildMentoringResponsesWithBatchQuery( // N+1 을 해결하면서 멘토링 상대방의 정보를 조회 + List mentorings, Function getPartnerId + ) { + List partnerUserId = mentorings.stream() + .map(getPartnerId) + .distinct() .toList(); + List partnerUsers = siteUserRepository.findAllById(partnerUserId); + Map partnerUserMap = partnerUsers.stream() + .collect(Collectors.toMap(SiteUser::getId, Function.identity())); - return MentoringListResponse.from(mentoringResponses); + List mentoringResponses = new ArrayList<>(); + for (Mentoring mentoring : mentorings) { + long partnerId = getPartnerId.apply(mentoring); + SiteUser partnerUser = partnerUserMap.get(partnerId); + mentoringResponses.add(MentoringResponse.from(mentoring, partnerUser)); + } + return mentoringResponses; } @Transactional(readOnly = true) From 787de594ab811424238d705c7ead2f8196af0eea Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Fri, 1 Aug 2025 07:50:23 +0900 Subject: [PATCH 3/9] =?UTF-8?q?test:=20=ED=8E=98=EC=9D=B4=EC=A7=80?= =?UTF-8?q?=EB=84=A4=EC=9D=B4=EC=85=98=EC=9C=BC=EB=A1=9C=20=EB=B0=94?= =?UTF-8?q?=EB=80=90=20=EA=B2=83=20=ED=85=8C=EC=8A=A4=ED=8A=B8=EC=BD=94?= =?UTF-8?q?=EB=93=9C=EC=97=90=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 추가로, 멘토링에 mentor_id와 mentee_id가 unique 해야 할 것을 염두에 두고, 테스트 코드 수정 - 테스트 단위가 작아지도록 수정 --- .../service/MentoringQueryServiceTest.java | 159 ++++++++++++++---- 1 file changed, 128 insertions(+), 31 deletions(-) diff --git a/src/test/java/com/example/solidconnection/mentor/service/MentoringQueryServiceTest.java b/src/test/java/com/example/solidconnection/mentor/service/MentoringQueryServiceTest.java index 6e61a4a7a..a58f5eb5c 100644 --- a/src/test/java/com/example/solidconnection/mentor/service/MentoringQueryServiceTest.java +++ b/src/test/java/com/example/solidconnection/mentor/service/MentoringQueryServiceTest.java @@ -1,15 +1,16 @@ package com.example.solidconnection.mentor.service; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertAll; +import com.example.solidconnection.common.VerifyStatus; +import com.example.solidconnection.common.dto.SliceResponse; import com.example.solidconnection.mentor.domain.Mentor; import com.example.solidconnection.mentor.domain.Mentoring; import com.example.solidconnection.mentor.dto.MentoringCountResponse; -import com.example.solidconnection.mentor.dto.MentoringListResponse; import com.example.solidconnection.mentor.dto.MentoringResponse; import com.example.solidconnection.mentor.fixture.MentorFixture; import com.example.solidconnection.mentor.fixture.MentoringFixture; +import com.example.solidconnection.mentor.repository.MentoringRepository; import com.example.solidconnection.siteuser.domain.SiteUser; import com.example.solidconnection.siteuser.fixture.SiteUserFixture; import com.example.solidconnection.support.TestContainerSpringBootTest; @@ -18,6 +19,8 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; @TestContainerSpringBootTest @DisplayName("멘토링 조회 서비스 테스트") @@ -35,49 +38,143 @@ class MentoringQueryServiceTest { @Autowired private MentoringFixture mentoringFixture; - private SiteUser mentorUser; - private SiteUser menteeUser; - private Mentor mentor; + @Autowired + private MentoringRepository mentoringRepository; + + private SiteUser mentorUser1, mentorUser2; + private SiteUser menteeUser1, menteeUser2, menteeUser3; + private Mentor mentor1, mentor2, mentor3; + private Pageable pageable; @BeforeEach void setUp() { - mentorUser = siteUserFixture.멘토(1, "mentor1"); - menteeUser = siteUserFixture.사용자(2, "mentee1"); - mentor = mentorFixture.멘토(mentorUser.getId(), 1L); + mentorUser1 = siteUserFixture.멘토(1, "mentor1"); + mentorUser2 = siteUserFixture.멘토(2, "mentor2"); + SiteUser mentorUser3 = siteUserFixture.멘토(3, "mentor3"); + menteeUser1 = siteUserFixture.사용자(1, "mentee1"); + menteeUser2 = siteUserFixture.사용자(2, "mentee2"); + menteeUser3 = siteUserFixture.사용자(3, "mentee3"); + mentor1 = mentorFixture.멘토(mentorUser1.getId(), 1L); + mentor2 = mentorFixture.멘토(mentorUser2.getId(), 1L); + mentor3 = mentorFixture.멘토(mentorUser3.getId(), 1L); + pageable = PageRequest.of(0, 3); + } + + @Nested + class 멘토의_멘토링_목록_조회_테스트 { + + @Test + void 모든_상태의_멘토링_목록을_조회한다() { + // given + Mentoring mentoring1 = mentoringFixture.대기중_멘토링(mentor1.getId(), menteeUser1.getId()); + Mentoring mentoring2 = mentoringFixture.승인된_멘토링(mentor1.getId(), menteeUser2.getId()); + Mentoring mentoring3 = mentoringFixture.거절된_멘토링(mentor1.getId(), menteeUser3.getId()); + + // when + SliceResponse response = mentoringQueryService.getMentoringsForMentor(mentorUser1.getId(), pageable); + + // then + assertThat(response.content()).extracting(MentoringResponse::mentoringId) + .containsExactlyInAnyOrder( + mentoring1.getId(), + mentoring2.getId(), + mentoring3.getId() + ); + } + + @Test + void 멘토링_상대의_정보를_포함한다() { + // given + mentoringFixture.대기중_멘토링(mentor1.getId(), menteeUser1.getId()); + mentoringFixture.승인된_멘토링(mentor1.getId(), menteeUser2.getId()); + + // when + SliceResponse response = mentoringQueryService.getMentoringsForMentor(mentorUser1.getId(), pageable); + + // then + assertThat(response.content()).extracting(MentoringResponse::nickname) + .containsExactlyInAnyOrder( + menteeUser1.getNickname(), + menteeUser2.getNickname() + ); + } + + @Test + void 멘토링이_없는_경우_빈_리스트를_반환한다() { + // when + SliceResponse response = mentoringQueryService.getMentoringsForMentor(mentorUser1.getId(), pageable); + + // then + assertThat(response.content()).isEmpty(); + } } @Nested - class 멘토링_목록_조회_테스트 { + class 멘티의_멘토링_목록_조회_테스트 { + + @Test + void 승인된_멘토링_목록을_조회한다() { + // given + Mentoring mentoring1 = mentoringFixture.승인된_멘토링(mentor1.getId(), menteeUser1.getId()); + Mentoring mentoring2 = mentoringFixture.승인된_멘토링(mentor2.getId(), menteeUser1.getId()); + mentoringFixture.대기중_멘토링(mentor3.getId(), menteeUser1.getId()); + + // when + SliceResponse response = mentoringQueryService.getMentoringsForMentee( + menteeUser1.getId(), VerifyStatus.APPROVED, pageable); + + // then + assertThat(response.content()).extracting(MentoringResponse::mentoringId) + .containsExactlyInAnyOrder( + mentoring1.getId(), + mentoring2.getId() + ); + } + + @Test + void 대기중인_멘토링_목록을_조회한다() { + // given + Mentoring mentoring1 = mentoringFixture.대기중_멘토링(mentor1.getId(), menteeUser1.getId()); + Mentoring mentoring2 = mentoringFixture.대기중_멘토링(mentor2.getId(), menteeUser1.getId()); + mentoringFixture.승인된_멘토링(mentor3.getId(), menteeUser1.getId()); + + // when + SliceResponse response = mentoringQueryService.getMentoringsForMentee( + menteeUser1.getId(), VerifyStatus.PENDING, pageable); + + // then + assertThat(response.content()).extracting(MentoringResponse::mentoringId) + .containsExactlyInAnyOrder( + mentoring1.getId(), + mentoring2.getId() + ); + } @Test - void 멘토의_모든_멘토링을_조회한다() { + void 멘토링_상대의_정보를_포함한다() { // given - Mentoring mentoring1 = mentoringFixture.대기중_멘토링(mentor.getId(), menteeUser.getId()); - Mentoring mentoring2 = mentoringFixture.승인된_멘토링(mentor.getId(), menteeUser.getId()); - Mentoring mentoring3 = mentoringFixture.거절된_멘토링(mentor.getId(), menteeUser.getId()); + mentoringFixture.승인된_멘토링(mentor1.getId(), menteeUser1.getId()); + mentoringFixture.승인된_멘토링(mentor2.getId(), menteeUser1.getId()); // when - MentoringListResponse responses = mentoringQueryService.getMentorings(mentorUser.getId()); + SliceResponse response = mentoringQueryService.getMentoringsForMentee( + menteeUser1.getId(), VerifyStatus.APPROVED, pageable); // then - assertAll( - () -> assertThat(responses.requests()).hasSize(3), - () -> assertThat(responses.requests()).extracting(MentoringResponse::mentoringId) - .containsExactlyInAnyOrder( - mentoring1.getId(), - mentoring2.getId(), - mentoring3.getId() - ) - ); + assertThat(response.content()).extracting(MentoringResponse::nickname) + .containsExactlyInAnyOrder( + mentorUser1.getNickname(), + mentorUser2.getNickname() + ); } @Test void 멘토링이_없는_경우_빈_리스트를_반환한다() { // when - MentoringListResponse responses = mentoringQueryService.getMentorings(mentorUser.getId()); + SliceResponse response = mentoringQueryService.getMentoringsForMentor(mentorUser1.getId(), pageable); // then - assertThat(responses.requests()).isEmpty(); + assertThat(response.content()).isEmpty(); } } @@ -87,12 +184,12 @@ class 새_멘토링_개수_조회_테스트 { @Test void 확인되지_않은_멘토링_개수를_반환한다() { // given - mentoringFixture.확인되지_않은_멘토링(mentor.getId(), menteeUser.getId()); - mentoringFixture.확인되지_않은_멘토링(mentor.getId(), menteeUser.getId()); - mentoringFixture.승인된_멘토링(mentor.getId(), menteeUser.getId()); + mentoringFixture.확인되지_않은_멘토링(mentor1.getId(), menteeUser1.getId()); + mentoringFixture.확인되지_않은_멘토링(mentor1.getId(), menteeUser2.getId()); + mentoringFixture.승인된_멘토링(mentor1.getId(), menteeUser3.getId()); // when - MentoringCountResponse response = mentoringQueryService.getNewMentoringsCount(mentorUser.getId()); + MentoringCountResponse response = mentoringQueryService.getNewMentoringsCount(mentorUser1.getId()); // then assertThat(response.uncheckedCount()).isEqualTo(2); @@ -101,10 +198,10 @@ class 새_멘토링_개수_조회_테스트 { @Test void 확인되지_않은_멘토링이_없으면_0을_반환한다() { // given - mentoringFixture.승인된_멘토링(mentor.getId(), menteeUser.getId()); + mentoringFixture.승인된_멘토링(mentor1.getId(), menteeUser1.getId()); // when - MentoringCountResponse response = mentoringQueryService.getNewMentoringsCount(mentorUser.getId()); + MentoringCountResponse response = mentoringQueryService.getNewMentoringsCount(mentorUser1.getId()); // then assertThat(response.uncheckedCount()).isZero(); From 5811329acf19cc0992414e904c044dcb83fdac51 Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Fri, 1 Aug 2025 08:02:46 +0900 Subject: [PATCH 4/9] =?UTF-8?q?refactor:=20=EB=A9=98=ED=86=A0=EB=A7=81=20?= =?UTF-8?q?=EC=B2=B4=ED=81=AC=20=EB=A1=9C=EC=A7=81=20=EC=84=9C=EB=B9=84?= =?UTF-8?q?=EC=8A=A4=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MentoringForMentorController.java | 5 +- .../repository/MentoringRepository.java | 2 +- .../mentor/service/MentoringCheckService.java | 30 +++++++ .../service/MentoringCommandService.java | 16 ---- .../mentor/service/MentoringQueryService.java | 11 --- .../service/MentoringCheckServiceTest.java | 90 +++++++++++++++++++ .../service/MentoringCommandServiceTest.java | 41 --------- .../service/MentoringQueryServiceTest.java | 35 -------- 8 files changed, 125 insertions(+), 105 deletions(-) create mode 100644 src/main/java/com/example/solidconnection/mentor/service/MentoringCheckService.java create mode 100644 src/test/java/com/example/solidconnection/mentor/service/MentoringCheckServiceTest.java diff --git a/src/main/java/com/example/solidconnection/mentor/controller/MentoringForMentorController.java b/src/main/java/com/example/solidconnection/mentor/controller/MentoringForMentorController.java index 606f75759..0aae49776 100644 --- a/src/main/java/com/example/solidconnection/mentor/controller/MentoringForMentorController.java +++ b/src/main/java/com/example/solidconnection/mentor/controller/MentoringForMentorController.java @@ -8,6 +8,7 @@ import com.example.solidconnection.mentor.dto.MentoringConfirmResponse; import com.example.solidconnection.mentor.dto.MentoringCountResponse; import com.example.solidconnection.mentor.dto.MentoringResponse; +import com.example.solidconnection.mentor.service.MentoringCheckService; import com.example.solidconnection.mentor.service.MentoringCommandService; import com.example.solidconnection.mentor.service.MentoringQueryService; import com.example.solidconnection.security.annotation.RequireRoleAccess; @@ -34,6 +35,7 @@ public class MentoringForMentorController { private final MentoringCommandService mentoringCommandService; private final MentoringQueryService mentoringQueryService; + private final MentoringCheckService mentoringCheckService; @RequireRoleAccess(roles = {Role.ADMIN, Role.MENTOR}) @GetMapping @@ -75,6 +77,7 @@ public ResponseEntity checkMentoring( public ResponseEntity getUncheckedMentoringsCount( @AuthorizedUser long siteUserId ) { - return ResponseEntity.ok().build(); + MentoringCountResponse response = mentoringCheckService.getUncheckedMentoringCount(siteUserId); + return ResponseEntity.ok(response); } } diff --git a/src/main/java/com/example/solidconnection/mentor/repository/MentoringRepository.java b/src/main/java/com/example/solidconnection/mentor/repository/MentoringRepository.java index e3a5bd4cd..16caf3318 100644 --- a/src/main/java/com/example/solidconnection/mentor/repository/MentoringRepository.java +++ b/src/main/java/com/example/solidconnection/mentor/repository/MentoringRepository.java @@ -11,7 +11,7 @@ public interface MentoringRepository extends JpaRepository { - int countByMentorIdAndCheckedAtIsNull(long mentorId); + int countByMentorIdAndCheckedAtByMentorIsNull(long mentorId); boolean existsByMentorIdAndMenteeId(long mentorId, long menteeId); diff --git a/src/main/java/com/example/solidconnection/mentor/service/MentoringCheckService.java b/src/main/java/com/example/solidconnection/mentor/service/MentoringCheckService.java new file mode 100644 index 000000000..563a9df7f --- /dev/null +++ b/src/main/java/com/example/solidconnection/mentor/service/MentoringCheckService.java @@ -0,0 +1,30 @@ +package com.example.solidconnection.mentor.service; + +import static com.example.solidconnection.common.exception.ErrorCode.MENTOR_NOT_FOUND; + +import com.example.solidconnection.common.exception.CustomException; +import com.example.solidconnection.mentor.domain.Mentor; +import com.example.solidconnection.mentor.dto.MentoringCountResponse; +import com.example.solidconnection.mentor.repository.MentorRepository; +import com.example.solidconnection.mentor.repository.MentoringRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +public class MentoringCheckService { + + private final MentorRepository mentorRepository; + private final MentoringRepository mentoringRepository; + + @Transactional(readOnly = true) + public MentoringCountResponse getUncheckedMentoringCount(long siteUserId) { + Mentor mentor = mentorRepository.findBySiteUserId(siteUserId) + .orElseThrow(() -> new CustomException(MENTOR_NOT_FOUND)); + + int count = mentoringRepository.countByMentorIdAndCheckedAtByMentorIsNull(mentor.getId()); + + return MentoringCountResponse.from(count); + } +} diff --git a/src/main/java/com/example/solidconnection/mentor/service/MentoringCommandService.java b/src/main/java/com/example/solidconnection/mentor/service/MentoringCommandService.java index ca35f6c95..dd4e98936 100644 --- a/src/main/java/com/example/solidconnection/mentor/service/MentoringCommandService.java +++ b/src/main/java/com/example/solidconnection/mentor/service/MentoringCommandService.java @@ -11,7 +11,6 @@ import com.example.solidconnection.mentor.domain.Mentoring; import com.example.solidconnection.mentor.dto.MentoringApplyRequest; import com.example.solidconnection.mentor.dto.MentoringApplyResponse; -import com.example.solidconnection.mentor.dto.MentoringCheckResponse; import com.example.solidconnection.mentor.dto.MentoringConfirmRequest; import com.example.solidconnection.mentor.dto.MentoringConfirmResponse; import com.example.solidconnection.mentor.repository.MentorRepository; @@ -60,21 +59,6 @@ private void validateMentoringNotConfirmed(Mentoring mentoring) { } } - @Transactional - public MentoringCheckResponse checkMentoring(long siteUserId, long mentoringId) { - Mentoring mentoring = mentoringRepository.findById(mentoringId) - .orElseThrow(() -> new CustomException(MENTORING_NOT_FOUND)); - - Mentor mentor = mentorRepository.findBySiteUserId(siteUserId) - .orElseThrow(() -> new CustomException(MENTOR_NOT_FOUND)); - - validateMentoringOwnership(mentor, mentoring); - - mentoring.check(); - - return MentoringCheckResponse.from(mentoring.getId()); - } - // 멘토는 본인의 멘토링에 대해 confirm 및 check해야 한다. private void validateMentoringOwnership(Mentor mentor, Mentoring mentoring) { if (mentoring.getMentorId() != mentor.getId()) { diff --git a/src/main/java/com/example/solidconnection/mentor/service/MentoringQueryService.java b/src/main/java/com/example/solidconnection/mentor/service/MentoringQueryService.java index b8ede796c..4a2545733 100644 --- a/src/main/java/com/example/solidconnection/mentor/service/MentoringQueryService.java +++ b/src/main/java/com/example/solidconnection/mentor/service/MentoringQueryService.java @@ -7,7 +7,6 @@ import com.example.solidconnection.common.exception.CustomException; import com.example.solidconnection.mentor.domain.Mentor; import com.example.solidconnection.mentor.domain.Mentoring; -import com.example.solidconnection.mentor.dto.MentoringCountResponse; import com.example.solidconnection.mentor.dto.MentoringResponse; import com.example.solidconnection.mentor.repository.MentorRepository; import com.example.solidconnection.mentor.repository.MentoringRepository; @@ -79,14 +78,4 @@ private List buildMentoringResponsesWithBatchQuery( // N+1 } return mentoringResponses; } - - @Transactional(readOnly = true) - public MentoringCountResponse getNewMentoringsCount(long siteUserId) { - Mentor mentor = mentorRepository.findBySiteUserId(siteUserId) - .orElseThrow(() -> new CustomException(MENTOR_NOT_FOUND)); - - int count = mentoringRepository.countByMentorIdAndCheckedAtIsNull(mentor.getId()); - - return MentoringCountResponse.from(count); - } } diff --git a/src/test/java/com/example/solidconnection/mentor/service/MentoringCheckServiceTest.java b/src/test/java/com/example/solidconnection/mentor/service/MentoringCheckServiceTest.java new file mode 100644 index 000000000..50d7e54a7 --- /dev/null +++ b/src/test/java/com/example/solidconnection/mentor/service/MentoringCheckServiceTest.java @@ -0,0 +1,90 @@ +package com.example.solidconnection.mentor.service; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.example.solidconnection.mentor.domain.Mentor; +import com.example.solidconnection.mentor.dto.MentoringCountResponse; +import com.example.solidconnection.mentor.fixture.MentorFixture; +import com.example.solidconnection.mentor.fixture.MentoringFixture; +import com.example.solidconnection.mentor.repository.MentoringRepository; +import com.example.solidconnection.siteuser.domain.SiteUser; +import com.example.solidconnection.siteuser.fixture.SiteUserFixture; +import com.example.solidconnection.support.TestContainerSpringBootTest; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; + +@TestContainerSpringBootTest +@DisplayName("멘토링 확인 서비스 테스트") +class MentoringCheckServiceTest { + + @Autowired + private MentoringRepository mentoringRepository; + + @Autowired + private MentoringCheckService mentoringCheckService; + + @Autowired + private MentoringFixture mentoringFixture; + + @Autowired + private SiteUserFixture siteUserFixture; + + @Autowired + private MentorFixture mentorFixture; + + + private SiteUser mentorUser1, mentorUser2; + private SiteUser menteeUser1, menteeUser2, menteeUser3; + private Mentor mentor1, mentor2, mentor3; + private Pageable pageable; + + @BeforeEach + void setUp() { + mentorUser1 = siteUserFixture.멘토(1, "mentor1"); + mentorUser2 = siteUserFixture.멘토(2, "mentor2"); + SiteUser mentorUser3 = siteUserFixture.멘토(3, "mentor3"); + menteeUser1 = siteUserFixture.사용자(1, "mentee1"); + menteeUser2 = siteUserFixture.사용자(2, "mentee2"); + menteeUser3 = siteUserFixture.사용자(3, "mentee3"); + mentor1 = mentorFixture.멘토(mentorUser1.getId(), 1L); + mentor2 = mentorFixture.멘토(mentorUser2.getId(), 1L); + mentor3 = mentorFixture.멘토(mentorUser3.getId(), 1L); + pageable = PageRequest.of(0, 3); + } + + + @Nested + class 확인하지_않은_멘토링_개수_조회_테스트 { + + @Test + void 확인하지_않은_멘토링_개수를_반환한다() { + // given + mentoringFixture.확인되지_않은_멘토링(mentor1.getId(), menteeUser1.getId()); + mentoringFixture.확인되지_않은_멘토링(mentor1.getId(), menteeUser2.getId()); + mentoringFixture.승인된_멘토링(mentor1.getId(), menteeUser3.getId()); + + // when + MentoringCountResponse response = mentoringCheckService.getUncheckedMentoringCount(mentorUser1.getId()); + + // then + assertThat(response.uncheckedCount()).isEqualTo(2); + } + + @Test + void 확인되지_않은_멘토링이_없으면_0을_반환한다() { + // given + mentoringFixture.승인된_멘토링(mentor1.getId(), menteeUser1.getId()); + + // when + MentoringCountResponse response = mentoringCheckService.getUncheckedMentoringCount(mentorUser1.getId()); + + // then + assertThat(response.uncheckedCount()).isZero(); + } + } +} diff --git a/src/test/java/com/example/solidconnection/mentor/service/MentoringCommandServiceTest.java b/src/test/java/com/example/solidconnection/mentor/service/MentoringCommandServiceTest.java index a7cea53bb..980ec456d 100644 --- a/src/test/java/com/example/solidconnection/mentor/service/MentoringCommandServiceTest.java +++ b/src/test/java/com/example/solidconnection/mentor/service/MentoringCommandServiceTest.java @@ -13,7 +13,6 @@ import com.example.solidconnection.mentor.domain.Mentoring; import com.example.solidconnection.mentor.dto.MentoringApplyRequest; import com.example.solidconnection.mentor.dto.MentoringApplyResponse; -import com.example.solidconnection.mentor.dto.MentoringCheckResponse; import com.example.solidconnection.mentor.dto.MentoringConfirmRequest; import com.example.solidconnection.mentor.dto.MentoringConfirmResponse; import com.example.solidconnection.mentor.fixture.MentorFixture; @@ -173,44 +172,4 @@ class 멘토링_승인_거절_테스트 { .hasMessage(MENTORING_NOT_FOUND.getMessage()); } } - - @Nested - class 멘토링_확인_테스트 { - - @Test - void 멘토링을_성공적으로_확인_처리한다() { - // given - Mentoring mentoring = mentoringFixture.확인되지_않은_멘토링(mentor1.getId(), menteeUser.getId()); - - // when - MentoringCheckResponse response = mentoringCommandService.checkMentoring(mentorUser1.getId(), mentoring.getId()); - - // then - Mentoring checked = mentoringRepository.findById(response.mentoringId()).orElseThrow(); - - assertThat(checked.getCheckedAt()).isNotNull(); - } - - @Test - void 다른_멘토의_멘토링은_확인할_수_없다() { - // given - Mentoring mentoring = mentoringFixture.확인되지_않은_멘토링(mentor1.getId(), menteeUser.getId()); - - // when & then - assertThatThrownBy(() -> mentoringCommandService.checkMentoring(mentorUser2.getId(), mentoring.getId())) - .isInstanceOf(CustomException.class) - .hasMessage(UNAUTHORIZED_MENTORING.getMessage()); - } - - @Test - void 존재하지_않는_멘토링_아이디로_요청시_예외가_발생한다() { - // given - long invalidMentoringId = 9999L; - - // when & then - assertThatThrownBy(() -> mentoringCommandService.checkMentoring(mentorUser1.getId(), invalidMentoringId)) - .isInstanceOf(CustomException.class) - .hasMessage(MENTORING_NOT_FOUND.getMessage()); - } - } } diff --git a/src/test/java/com/example/solidconnection/mentor/service/MentoringQueryServiceTest.java b/src/test/java/com/example/solidconnection/mentor/service/MentoringQueryServiceTest.java index a58f5eb5c..3dbb68466 100644 --- a/src/test/java/com/example/solidconnection/mentor/service/MentoringQueryServiceTest.java +++ b/src/test/java/com/example/solidconnection/mentor/service/MentoringQueryServiceTest.java @@ -6,11 +6,9 @@ import com.example.solidconnection.common.dto.SliceResponse; import com.example.solidconnection.mentor.domain.Mentor; import com.example.solidconnection.mentor.domain.Mentoring; -import com.example.solidconnection.mentor.dto.MentoringCountResponse; import com.example.solidconnection.mentor.dto.MentoringResponse; import com.example.solidconnection.mentor.fixture.MentorFixture; import com.example.solidconnection.mentor.fixture.MentoringFixture; -import com.example.solidconnection.mentor.repository.MentoringRepository; import com.example.solidconnection.siteuser.domain.SiteUser; import com.example.solidconnection.siteuser.fixture.SiteUserFixture; import com.example.solidconnection.support.TestContainerSpringBootTest; @@ -38,9 +36,6 @@ class MentoringQueryServiceTest { @Autowired private MentoringFixture mentoringFixture; - @Autowired - private MentoringRepository mentoringRepository; - private SiteUser mentorUser1, mentorUser2; private SiteUser menteeUser1, menteeUser2, menteeUser3; private Mentor mentor1, mentor2, mentor3; @@ -177,34 +172,4 @@ class 멘티의_멘토링_목록_조회_테스트 { assertThat(response.content()).isEmpty(); } } - - @Nested - class 새_멘토링_개수_조회_테스트 { - - @Test - void 확인되지_않은_멘토링_개수를_반환한다() { - // given - mentoringFixture.확인되지_않은_멘토링(mentor1.getId(), menteeUser1.getId()); - mentoringFixture.확인되지_않은_멘토링(mentor1.getId(), menteeUser2.getId()); - mentoringFixture.승인된_멘토링(mentor1.getId(), menteeUser3.getId()); - - // when - MentoringCountResponse response = mentoringQueryService.getNewMentoringsCount(mentorUser1.getId()); - - // then - assertThat(response.uncheckedCount()).isEqualTo(2); - } - - @Test - void 확인되지_않은_멘토링이_없으면_0을_반환한다() { - // given - mentoringFixture.승인된_멘토링(mentor1.getId(), menteeUser1.getId()); - - // when - MentoringCountResponse response = mentoringQueryService.getNewMentoringsCount(mentorUser1.getId()); - - // then - assertThat(response.uncheckedCount()).isZero(); - } - } } From 62a5152ffc6fb101286d86b622369ff2b0891aca Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Fri, 1 Aug 2025 10:08:17 +0900 Subject: [PATCH 5/9] =?UTF-8?q?refactor:=20=EB=A9=98=ED=86=A0=EB=A7=81=20?= =?UTF-8?q?=ED=85=8C=EC=9D=B4=EB=B8=94=EC=97=90=20checked=5Fat=5Fby=5Fment?= =?UTF-8?q?ee=20=EC=BB=AC=EB=9F=BC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mentor/domain/Mentoring.java | 17 ++++++++++++----- .../V27__add_checked_at_by_mentee_column.sql | 5 +++++ .../mentor/fixture/MentoringFixture.java | 6 +++--- .../mentor/fixture/MentoringFixtureBuilder.java | 15 +++++++++++---- .../service/MentoringCommandServiceTest.java | 4 ++-- 5 files changed, 33 insertions(+), 14 deletions(-) create mode 100644 src/main/resources/db/migration/V27__add_checked_at_by_mentee_column.sql diff --git a/src/main/java/com/example/solidconnection/mentor/domain/Mentoring.java b/src/main/java/com/example/solidconnection/mentor/domain/Mentoring.java index 47226076d..0eb0949a5 100644 --- a/src/main/java/com/example/solidconnection/mentor/domain/Mentoring.java +++ b/src/main/java/com/example/solidconnection/mentor/domain/Mentoring.java @@ -40,7 +40,10 @@ public class Mentoring { private ZonedDateTime confirmedAt; @Column - private ZonedDateTime checkedAt; + private ZonedDateTime checkedAtByMentor; + + @Column + private ZonedDateTime checkedAtByMentee; @Column(nullable = false) @Enumerated(EnumType.STRING) @@ -67,12 +70,16 @@ public void confirm(VerifyStatus status) { this.verifyStatus = status; this.confirmedAt = ZonedDateTime.now(UTC).truncatedTo(MICROS); - if (this.checkedAt == null) { - this.checkedAt = this.confirmedAt; + if (this.checkedAtByMentor == null) { + this.checkedAtByMentor = this.confirmedAt; } } - public void check() { - this.checkedAt = ZonedDateTime.now(UTC).truncatedTo(MICROS); + public void checkByMentor() { + this.checkedAtByMentor = ZonedDateTime.now(UTC).truncatedTo(MICROS); + } + + public void checkByMentee() { + this.checkedAtByMentee = ZonedDateTime.now(UTC).truncatedTo(MICROS); } } diff --git a/src/main/resources/db/migration/V27__add_checked_at_by_mentee_column.sql b/src/main/resources/db/migration/V27__add_checked_at_by_mentee_column.sql new file mode 100644 index 000000000..41e1ad637 --- /dev/null +++ b/src/main/resources/db/migration/V27__add_checked_at_by_mentee_column.sql @@ -0,0 +1,5 @@ +ALTER TABLE mentoring + RENAME COLUMN checked_at TO checked_at_by_mentor; + +ALTER TABLE mentoring + ADD COLUMN checked_at_by_mentee DATETIME(6) NULL; diff --git a/src/test/java/com/example/solidconnection/mentor/fixture/MentoringFixture.java b/src/test/java/com/example/solidconnection/mentor/fixture/MentoringFixture.java index 07925628e..4779c643e 100644 --- a/src/test/java/com/example/solidconnection/mentor/fixture/MentoringFixture.java +++ b/src/test/java/com/example/solidconnection/mentor/fixture/MentoringFixture.java @@ -29,7 +29,7 @@ public class MentoringFixture { .menteeId(menteeId) .verifyStatus(VerifyStatus.APPROVED) .confirmedAt(now) - .checkedAt(now) + .checkedAtByMentor(now) .create(); } @@ -40,7 +40,7 @@ public class MentoringFixture { .menteeId(menteeId) .verifyStatus(VerifyStatus.REJECTED) .confirmedAt(now) - .checkedAt(now) + .checkedAtByMentor(now) .create(); } @@ -48,7 +48,7 @@ public class MentoringFixture { return mentoringFixtureBuilder.mentoring() .mentorId(mentorId) .menteeId(menteeId) - .checkedAt(null) + .checkedAtByMentor(null) .create(); } diff --git a/src/test/java/com/example/solidconnection/mentor/fixture/MentoringFixtureBuilder.java b/src/test/java/com/example/solidconnection/mentor/fixture/MentoringFixtureBuilder.java index 857c18ea8..f4e905b3a 100644 --- a/src/test/java/com/example/solidconnection/mentor/fixture/MentoringFixtureBuilder.java +++ b/src/test/java/com/example/solidconnection/mentor/fixture/MentoringFixtureBuilder.java @@ -15,7 +15,8 @@ public class MentoringFixtureBuilder { private ZonedDateTime createdAt; private ZonedDateTime confirmedAt; - private ZonedDateTime checkedAt; + private ZonedDateTime checkedAtByMentor; + private ZonedDateTime checkedAtByMentee; private VerifyStatus verifyStatus = VerifyStatus.PENDING; private long mentorId; private long menteeId; @@ -34,8 +35,13 @@ public MentoringFixtureBuilder confirmedAt(ZonedDateTime confirmedAt) { return this; } - public MentoringFixtureBuilder checkedAt(ZonedDateTime checkedAt) { - this.checkedAt = checkedAt; + public MentoringFixtureBuilder checkedAtByMentor(ZonedDateTime checkedAtByMentor) { + this.checkedAtByMentor = checkedAtByMentor; + return this; + } + + public MentoringFixtureBuilder checkedAtByMentee(ZonedDateTime checkedAtByMentor) { + this.checkedAtByMentor = checkedAtByMentor; return this; } @@ -59,7 +65,8 @@ public Mentoring create() { null, createdAt, confirmedAt, - checkedAt, + checkedAtByMentor, + checkedAtByMentee, verifyStatus, mentorId, menteeId diff --git a/src/test/java/com/example/solidconnection/mentor/service/MentoringCommandServiceTest.java b/src/test/java/com/example/solidconnection/mentor/service/MentoringCommandServiceTest.java index 980ec456d..2a731a8b5 100644 --- a/src/test/java/com/example/solidconnection/mentor/service/MentoringCommandServiceTest.java +++ b/src/test/java/com/example/solidconnection/mentor/service/MentoringCommandServiceTest.java @@ -109,7 +109,7 @@ class 멘토링_승인_거절_테스트 { assertAll( () -> assertThat(confirmedMentoring.getVerifyStatus()).isEqualTo(VerifyStatus.APPROVED), () -> assertThat(confirmedMentoring.getConfirmedAt()).isNotNull(), - () -> assertThat(confirmedMentoring.getCheckedAt()).isNotNull(), + () -> assertThat(confirmedMentoring.getCheckedAtByMentor()).isNotNull(), () -> assertThat(mentor.getMenteeCount()).isEqualTo(beforeMenteeCount + 1) ); } @@ -131,7 +131,7 @@ class 멘토링_승인_거절_테스트 { assertAll( () -> assertThat(confirmedMentoring.getVerifyStatus()).isEqualTo(VerifyStatus.REJECTED), () -> assertThat(confirmedMentoring.getConfirmedAt()).isNotNull(), - () -> assertThat(confirmedMentoring.getCheckedAt()).isNotNull(), + () -> assertThat(confirmedMentoring.getCheckedAtByMentor()).isNotNull(), () -> assertThat(mentor.getMenteeCount()).isEqualTo(beforeMenteeCount) ); } From dea2714a7359dd2b219f1aa4316b125e8e8eda62 Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Sat, 2 Aug 2025 02:09:21 +0900 Subject: [PATCH 6/9] =?UTF-8?q?feat:=20=EB=A9=98=ED=86=A0,=EB=A9=98?= =?UTF-8?q?=ED=8B=B0=EC=9D=98=20=EB=A9=98=ED=86=A0=EB=A7=81=20=ED=99=95?= =?UTF-8?q?=EC=9D=B8=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MentoringForMenteeController.java | 11 +- .../MentoringForMentorController.java | 9 +- ...e.java => MentoringForMenteeResponse.java} | 8 +- .../dto/MentoringForMentorResponse.java | 24 ++++ .../mentor/dto/MentoringListResponse.java | 12 -- .../mentor/service/MentoringCheckService.java | 44 +++++++ .../mentor/service/MentoringQueryService.java | 42 ++++--- .../service/MentoringCheckServiceTest.java | 113 +++++++++++++++--- .../service/MentoringQueryServiceTest.java | 28 +++-- 9 files changed, 222 insertions(+), 69 deletions(-) rename src/main/java/com/example/solidconnection/mentor/dto/{MentoringResponse.java => MentoringForMenteeResponse.java} (69%) create mode 100644 src/main/java/com/example/solidconnection/mentor/dto/MentoringForMentorResponse.java delete mode 100644 src/main/java/com/example/solidconnection/mentor/dto/MentoringListResponse.java diff --git a/src/main/java/com/example/solidconnection/mentor/controller/MentoringForMenteeController.java b/src/main/java/com/example/solidconnection/mentor/controller/MentoringForMenteeController.java index 0fae22326..28683cd37 100644 --- a/src/main/java/com/example/solidconnection/mentor/controller/MentoringForMenteeController.java +++ b/src/main/java/com/example/solidconnection/mentor/controller/MentoringForMenteeController.java @@ -7,7 +7,8 @@ import com.example.solidconnection.mentor.dto.CheckedMentoringsResponse; import com.example.solidconnection.mentor.dto.MentoringApplyRequest; import com.example.solidconnection.mentor.dto.MentoringApplyResponse; -import com.example.solidconnection.mentor.dto.MentoringResponse; +import com.example.solidconnection.mentor.dto.MentoringForMenteeResponse; +import com.example.solidconnection.mentor.service.MentoringCheckService; import com.example.solidconnection.mentor.service.MentoringCommandService; import com.example.solidconnection.mentor.service.MentoringQueryService; import com.example.solidconnection.security.annotation.RequireRoleAccess; @@ -35,6 +36,7 @@ public class MentoringForMenteeController { private final MentoringCommandService mentoringCommandService; private final MentoringQueryService mentoringQueryService; + private final MentoringCheckService mentoringCheckService; @RequireRoleAccess(roles = Role.MENTEE) @PostMapping @@ -48,7 +50,7 @@ public ResponseEntity applyMentoring( @RequireRoleAccess(roles = Role.MENTEE) @GetMapping - public ResponseEntity> getMentorings( + public ResponseEntity> getMentorings( @AuthorizedUser long siteUserId, @RequestParam("verify-status") VerifyStatus verifyStatus, @PageableDefault(size = 3) @@ -58,7 +60,7 @@ public ResponseEntity> getMentorings( }) Pageable pageable ) { - SliceResponse response = mentoringQueryService.getMentoringsForMentee(siteUserId, verifyStatus, pageable); + SliceResponse response = mentoringQueryService.getMentoringsForMentee(siteUserId, verifyStatus, pageable); return ResponseEntity.ok(response); } @@ -68,6 +70,7 @@ public ResponseEntity checkMentorings( @AuthorizedUser long siteUserId, @Valid @RequestBody CheckMentoringRequest checkMentoringRequest ) { - return ResponseEntity.ok().build(); + CheckedMentoringsResponse response = mentoringCheckService.checkMentoringsForMentee(siteUserId, checkMentoringRequest); + return ResponseEntity.ok(response); } } diff --git a/src/main/java/com/example/solidconnection/mentor/controller/MentoringForMentorController.java b/src/main/java/com/example/solidconnection/mentor/controller/MentoringForMentorController.java index 0aae49776..b9fb2f63e 100644 --- a/src/main/java/com/example/solidconnection/mentor/controller/MentoringForMentorController.java +++ b/src/main/java/com/example/solidconnection/mentor/controller/MentoringForMentorController.java @@ -7,7 +7,7 @@ import com.example.solidconnection.mentor.dto.MentoringConfirmRequest; import com.example.solidconnection.mentor.dto.MentoringConfirmResponse; import com.example.solidconnection.mentor.dto.MentoringCountResponse; -import com.example.solidconnection.mentor.dto.MentoringResponse; +import com.example.solidconnection.mentor.dto.MentoringForMentorResponse; import com.example.solidconnection.mentor.service.MentoringCheckService; import com.example.solidconnection.mentor.service.MentoringCommandService; import com.example.solidconnection.mentor.service.MentoringQueryService; @@ -39,7 +39,7 @@ public class MentoringForMentorController { @RequireRoleAccess(roles = {Role.ADMIN, Role.MENTOR}) @GetMapping - public ResponseEntity> getMentorings( + public ResponseEntity> getMentorings( @AuthorizedUser long siteUserId, @PageableDefault(size = 3) @SortDefaults({ @@ -48,7 +48,7 @@ public ResponseEntity> getMentorings( }) Pageable pageable ) { - SliceResponse response = mentoringQueryService.getMentoringsForMentor(siteUserId, pageable); + SliceResponse response = mentoringQueryService.getMentoringsForMentor(siteUserId, pageable); return ResponseEntity.ok(response); } @@ -69,7 +69,8 @@ public ResponseEntity checkMentoring( @AuthorizedUser long siteUserId, @RequestBody CheckMentoringRequest mentoringCheckRequest ) { - return ResponseEntity.ok().build(); + CheckedMentoringsResponse response = mentoringCheckService.checkMentoringsForMentor(siteUserId, mentoringCheckRequest); + return ResponseEntity.ok(response); } @RequireRoleAccess(roles = {Role.ADMIN, Role.MENTOR}) diff --git a/src/main/java/com/example/solidconnection/mentor/dto/MentoringResponse.java b/src/main/java/com/example/solidconnection/mentor/dto/MentoringForMenteeResponse.java similarity index 69% rename from src/main/java/com/example/solidconnection/mentor/dto/MentoringResponse.java rename to src/main/java/com/example/solidconnection/mentor/dto/MentoringForMenteeResponse.java index 782538f2f..7f2591555 100644 --- a/src/main/java/com/example/solidconnection/mentor/dto/MentoringResponse.java +++ b/src/main/java/com/example/solidconnection/mentor/dto/MentoringForMenteeResponse.java @@ -4,7 +4,7 @@ import com.example.solidconnection.siteuser.domain.SiteUser; import java.time.ZonedDateTime; -public record MentoringResponse( +public record MentoringForMenteeResponse( long mentoringId, String profileImageUrl, String nickname, @@ -12,12 +12,12 @@ public record MentoringResponse( ZonedDateTime createdAt ) { - public static MentoringResponse from(Mentoring mentoring, SiteUser partner) { - return new MentoringResponse( + public static MentoringForMenteeResponse of(Mentoring mentoring, SiteUser partner) { + return new MentoringForMenteeResponse( mentoring.getId(), partner.getProfileImageUrl(), partner.getNickname(), - mentoring.getCheckedAt() != null, + mentoring.getCheckedAtByMentee() != null, mentoring.getCreatedAt() ); } diff --git a/src/main/java/com/example/solidconnection/mentor/dto/MentoringForMentorResponse.java b/src/main/java/com/example/solidconnection/mentor/dto/MentoringForMentorResponse.java new file mode 100644 index 000000000..9ee1889f6 --- /dev/null +++ b/src/main/java/com/example/solidconnection/mentor/dto/MentoringForMentorResponse.java @@ -0,0 +1,24 @@ +package com.example.solidconnection.mentor.dto; + +import com.example.solidconnection.mentor.domain.Mentoring; +import com.example.solidconnection.siteuser.domain.SiteUser; +import java.time.ZonedDateTime; + +public record MentoringForMentorResponse( + long mentoringId, + String profileImageUrl, + String nickname, + boolean isChecked, + ZonedDateTime createdAt +) { + + public static MentoringForMentorResponse of(Mentoring mentoring, SiteUser partner) { + return new MentoringForMentorResponse( + mentoring.getId(), + partner.getProfileImageUrl(), + partner.getNickname(), + mentoring.getCheckedAtByMentor() != null, + mentoring.getCreatedAt() + ); + } +} diff --git a/src/main/java/com/example/solidconnection/mentor/dto/MentoringListResponse.java b/src/main/java/com/example/solidconnection/mentor/dto/MentoringListResponse.java deleted file mode 100644 index cca80e06d..000000000 --- a/src/main/java/com/example/solidconnection/mentor/dto/MentoringListResponse.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.example.solidconnection.mentor.dto; - -import java.util.List; - -public record MentoringListResponse( - List requests -) { - - public static MentoringListResponse from(List requests) { - return new MentoringListResponse(requests); - } -} diff --git a/src/main/java/com/example/solidconnection/mentor/service/MentoringCheckService.java b/src/main/java/com/example/solidconnection/mentor/service/MentoringCheckService.java index 563a9df7f..5c73ad00b 100644 --- a/src/main/java/com/example/solidconnection/mentor/service/MentoringCheckService.java +++ b/src/main/java/com/example/solidconnection/mentor/service/MentoringCheckService.java @@ -1,12 +1,17 @@ package com.example.solidconnection.mentor.service; import static com.example.solidconnection.common.exception.ErrorCode.MENTOR_NOT_FOUND; +import static com.example.solidconnection.common.exception.ErrorCode.UNAUTHORIZED_MENTORING; import com.example.solidconnection.common.exception.CustomException; import com.example.solidconnection.mentor.domain.Mentor; +import com.example.solidconnection.mentor.domain.Mentoring; +import com.example.solidconnection.mentor.dto.CheckMentoringRequest; +import com.example.solidconnection.mentor.dto.CheckedMentoringsResponse; import com.example.solidconnection.mentor.dto.MentoringCountResponse; import com.example.solidconnection.mentor.repository.MentorRepository; import com.example.solidconnection.mentor.repository.MentoringRepository; +import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -18,6 +23,45 @@ public class MentoringCheckService { private final MentorRepository mentorRepository; private final MentoringRepository mentoringRepository; + @Transactional + public CheckedMentoringsResponse checkMentoringsForMentor(long mentorUserId, CheckMentoringRequest checkMentoringRequest) { + Mentor mentor = mentorRepository.findBySiteUserId(mentorUserId) + .orElseThrow(() -> new CustomException(MENTOR_NOT_FOUND)); + List mentorings = mentoringRepository.findAllById(checkMentoringRequest.checkedMentoringIds()); + List actualMentorIds = mentorings.stream() + .map(Mentoring::getMentorId) + .distinct() + .toList(); + + mentorings.forEach(Mentoring::checkByMentor); + validateMentoringsOwnership(actualMentorIds, mentor.getId()); + + return CheckedMentoringsResponse.from(mentorings); + } + + @Transactional + public CheckedMentoringsResponse checkMentoringsForMentee(long menteeUserId, CheckMentoringRequest checkMentoringRequest) { + List mentorings = mentoringRepository.findAllById(checkMentoringRequest.checkedMentoringIds()); + List actualMenteeIds = mentorings.stream() + .map(Mentoring::getMenteeId) + .distinct() + .toList(); + + validateMentoringsOwnership(actualMenteeIds, menteeUserId); + mentorings.forEach(Mentoring::checkByMentee); + + return CheckedMentoringsResponse.from(mentorings); + } + + private void validateMentoringsOwnership(List actualOwnerIds, long expectedOwnerId) { + actualOwnerIds.stream() + .filter(actualOwnerId -> actualOwnerId != expectedOwnerId) + .findFirst() + .ifPresent(ownerId -> { + throw new CustomException(UNAUTHORIZED_MENTORING); + }); + } + @Transactional(readOnly = true) public MentoringCountResponse getUncheckedMentoringCount(long siteUserId) { Mentor mentor = mentorRepository.findBySiteUserId(siteUserId) diff --git a/src/main/java/com/example/solidconnection/mentor/service/MentoringQueryService.java b/src/main/java/com/example/solidconnection/mentor/service/MentoringQueryService.java index 4a2545733..30349004d 100644 --- a/src/main/java/com/example/solidconnection/mentor/service/MentoringQueryService.java +++ b/src/main/java/com/example/solidconnection/mentor/service/MentoringQueryService.java @@ -7,7 +7,8 @@ import com.example.solidconnection.common.exception.CustomException; import com.example.solidconnection.mentor.domain.Mentor; import com.example.solidconnection.mentor.domain.Mentoring; -import com.example.solidconnection.mentor.dto.MentoringResponse; +import com.example.solidconnection.mentor.dto.MentoringForMenteeResponse; +import com.example.solidconnection.mentor.dto.MentoringForMentorResponse; import com.example.solidconnection.mentor.repository.MentorRepository; import com.example.solidconnection.mentor.repository.MentoringRepository; import com.example.solidconnection.siteuser.domain.SiteUser; @@ -15,6 +16,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.function.Function; import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; @@ -32,34 +34,45 @@ public class MentoringQueryService { private final SiteUserRepository siteUserRepository; @Transactional(readOnly = true) - public SliceResponse getMentoringsForMentee( + public SliceResponse getMentoringsForMentee( long siteUserId, VerifyStatus verifyStatus, Pageable pageable ) { Slice mentoringSlice = mentoringRepository.findAllByMenteeIdAndVerifyStatus(siteUserId, verifyStatus, pageable); + List mentorings = mentoringSlice.toList(); - List content = buildMentoringResponsesWithBatchQuery( - mentoringSlice.toList(), - Mentoring::getMentorId + Map mentoringToPartnerUser = mapMentoringToPartnerUserWithBatchQuery( + mentorings, Mentoring::getMentorId ); + List content = new ArrayList<>(); + for (Entry entry : mentoringToPartnerUser.entrySet()) { + content.add(MentoringForMenteeResponse.of(entry.getKey(), entry.getValue())); + } + return SliceResponse.of(content, mentoringSlice); } @Transactional(readOnly = true) - public SliceResponse getMentoringsForMentor(long siteUserId, Pageable pageable) { + public SliceResponse getMentoringsForMentor(long siteUserId, Pageable pageable) { Mentor mentor = mentorRepository.findBySiteUserId(siteUserId) .orElseThrow(() -> new CustomException(MENTOR_NOT_FOUND)); Slice mentoringSlice = mentoringRepository.findAllByMentorId(mentor.getId(), pageable); - List content = buildMentoringResponsesWithBatchQuery( + Map mentoringToPartnerUser = mapMentoringToPartnerUserWithBatchQuery( mentoringSlice.toList(), Mentoring::getMenteeId ); + List content = new ArrayList<>(); + for (Entry entry : mentoringToPartnerUser.entrySet()) { + content.add(MentoringForMentorResponse.of(entry.getKey(), entry.getValue())); + } + return SliceResponse.of(content, mentoringSlice); } - private List buildMentoringResponsesWithBatchQuery( // N+1 을 해결하면서 멘토링 상대방의 정보를 조회 + // N+1 을 해결하면서 멘토링 상대방의 정보를 조회 + private Map mapMentoringToPartnerUserWithBatchQuery( List mentorings, Function getPartnerId ) { List partnerUserId = mentorings.stream() @@ -67,15 +80,12 @@ private List buildMentoringResponsesWithBatchQuery( // N+1 .distinct() .toList(); List partnerUsers = siteUserRepository.findAllById(partnerUserId); - Map partnerUserMap = partnerUsers.stream() + Map partnerIdToPartnerUsermap = partnerUsers.stream() .collect(Collectors.toMap(SiteUser::getId, Function.identity())); - List mentoringResponses = new ArrayList<>(); - for (Mentoring mentoring : mentorings) { - long partnerId = getPartnerId.apply(mentoring); - SiteUser partnerUser = partnerUserMap.get(partnerId); - mentoringResponses.add(MentoringResponse.from(mentoring, partnerUser)); - } - return mentoringResponses; + return mentorings.stream().collect(Collectors.toMap( + Function.identity(), + mentoring -> partnerIdToPartnerUsermap.get(getPartnerId.apply(mentoring)) + )); } } diff --git a/src/test/java/com/example/solidconnection/mentor/service/MentoringCheckServiceTest.java b/src/test/java/com/example/solidconnection/mentor/service/MentoringCheckServiceTest.java index 50d7e54a7..c5f8a9463 100644 --- a/src/test/java/com/example/solidconnection/mentor/service/MentoringCheckServiceTest.java +++ b/src/test/java/com/example/solidconnection/mentor/service/MentoringCheckServiceTest.java @@ -1,8 +1,15 @@ package com.example.solidconnection.mentor.service; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.junit.jupiter.api.Assertions.assertAll; +import com.example.solidconnection.common.exception.CustomException; +import com.example.solidconnection.common.exception.ErrorCode; import com.example.solidconnection.mentor.domain.Mentor; +import com.example.solidconnection.mentor.domain.Mentoring; +import com.example.solidconnection.mentor.dto.CheckMentoringRequest; +import com.example.solidconnection.mentor.dto.CheckedMentoringsResponse; import com.example.solidconnection.mentor.dto.MentoringCountResponse; import com.example.solidconnection.mentor.fixture.MentorFixture; import com.example.solidconnection.mentor.fixture.MentoringFixture; @@ -10,13 +17,12 @@ import com.example.solidconnection.siteuser.domain.SiteUser; import com.example.solidconnection.siteuser.fixture.SiteUserFixture; import com.example.solidconnection.support.TestContainerSpringBootTest; +import java.util.List; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; @TestContainerSpringBootTest @DisplayName("멘토링 확인 서비스 테스트") @@ -41,7 +47,6 @@ class MentoringCheckServiceTest { private SiteUser mentorUser1, mentorUser2; private SiteUser menteeUser1, menteeUser2, menteeUser3; private Mentor mentor1, mentor2, mentor3; - private Pageable pageable; @BeforeEach void setUp() { @@ -54,37 +59,113 @@ void setUp() { mentor1 = mentorFixture.멘토(mentorUser1.getId(), 1L); mentor2 = mentorFixture.멘토(mentorUser2.getId(), 1L); mentor3 = mentorFixture.멘토(mentorUser3.getId(), 1L); - pageable = PageRequest.of(0, 3); } - @Nested - class 확인하지_않은_멘토링_개수_조회_테스트 { + class 멘토의_멘토링_확인_테스트 { @Test - void 확인하지_않은_멘토링_개수를_반환한다() { + void 멘토가_멘토링을_확인한다() { // given - mentoringFixture.확인되지_않은_멘토링(mentor1.getId(), menteeUser1.getId()); - mentoringFixture.확인되지_않은_멘토링(mentor1.getId(), menteeUser2.getId()); - mentoringFixture.승인된_멘토링(mentor1.getId(), menteeUser3.getId()); + Mentoring mentoring1 = mentoringFixture.확인되지_않은_멘토링(mentor1.getId(), menteeUser1.getId()); + Mentoring mentoring2 = mentoringFixture.확인되지_않은_멘토링(mentor1.getId(), menteeUser2.getId()); + Mentoring mentoring3 = mentoringFixture.확인되지_않은_멘토링(mentor1.getId(), menteeUser3.getId()); + CheckMentoringRequest request = new CheckMentoringRequest(List.of(mentoring1.getId(), mentoring2.getId())); // when - MentoringCountResponse response = mentoringCheckService.getUncheckedMentoringCount(mentorUser1.getId()); + CheckedMentoringsResponse response = mentoringCheckService.checkMentoringsForMentor(mentorUser1.getId(), request); // then - assertThat(response.uncheckedCount()).isEqualTo(2); + assertAll( + () -> assertThat(response.checkedMentoringIds()).containsExactlyInAnyOrder(mentoring1.getId(), mentoring2.getId()), + () -> assertThat(mentoringRepository.findById(mentoring1.getId())) + .hasValueSatisfying(mentoring -> assertThat(mentoring.getCheckedAtByMentor()).isNotNull()), + () -> assertThat(mentoringRepository.findById(mentoring2.getId())) + .hasValueSatisfying(mentoring -> assertThat(mentoring.getCheckedAtByMentor()).isNotNull()), + () -> assertThat(mentoringRepository.findById(mentoring3.getId())) + .hasValueSatisfying(mentoring -> assertThat(mentoring.getCheckedAtByMentor()).isNull()) + ); } @Test - void 확인되지_않은_멘토링이_없으면_0을_반환한다() { + void 다른_멘토의_멘토링은_확인하면_예외가_발생한다() { // given - mentoringFixture.승인된_멘토링(mentor1.getId(), menteeUser1.getId()); + Mentoring mentoring2 = mentoringFixture.확인되지_않은_멘토링(mentor2.getId(), menteeUser2.getId()); + CheckMentoringRequest request = new CheckMentoringRequest(List.of(mentoring2.getId())); + + // when, then + assertThatCode(() -> mentoringCheckService.checkMentoringsForMentor(mentorUser1.getId(), request)) + .isInstanceOf(CustomException.class) + .hasMessageContaining(ErrorCode.UNAUTHORIZED_MENTORING.getMessage()); + } + } + + @Nested + class 멘티의_멘토링_확인_테스트 { + + @Test + void 멘티가_멘토링을_확인한다() { + // given + Mentoring mentoring1 = mentoringFixture.확인되지_않은_멘토링(mentor1.getId(), menteeUser1.getId()); + Mentoring mentoring2 = mentoringFixture.확인되지_않은_멘토링(mentor2.getId(), menteeUser1.getId()); + Mentoring mentoring3 = mentoringFixture.확인되지_않은_멘토링(mentor3.getId(), menteeUser1.getId()); + CheckMentoringRequest request = new CheckMentoringRequest(List.of(mentoring1.getId(), mentoring2.getId())); // when - MentoringCountResponse response = mentoringCheckService.getUncheckedMentoringCount(mentorUser1.getId()); + CheckedMentoringsResponse response = mentoringCheckService.checkMentoringsForMentee(menteeUser1.getId(), request); // then - assertThat(response.uncheckedCount()).isZero(); + assertAll( + () -> assertThat(response.checkedMentoringIds()).containsExactlyInAnyOrder(mentoring1.getId(), mentoring2.getId()), + () -> assertThat(mentoringRepository.findById(mentoring1.getId())) + .hasValueSatisfying(mentoring -> assertThat(mentoring.getCheckedAtByMentee()).isNotNull()), + () -> assertThat(mentoringRepository.findById(mentoring2.getId())) + .hasValueSatisfying(mentoring -> assertThat(mentoring.getCheckedAtByMentee()).isNotNull()), + () -> assertThat(mentoringRepository.findById(mentoring3.getId())) + .hasValueSatisfying(mentoring -> assertThat(mentoring.getCheckedAtByMentee()).isNull()) + ); + } + + @Test + void 다른_멘티의_멘토링을_확인하면_예외가_발생한다() { + // given + Mentoring mentoring2 = mentoringFixture.확인되지_않은_멘토링(mentor2.getId(), menteeUser2.getId()); + CheckMentoringRequest request = new CheckMentoringRequest(List.of(mentoring2.getId())); + + // when, then + assertThatCode(() -> mentoringCheckService.checkMentoringsForMentee(menteeUser1.getId(), request)) + .isInstanceOf(CustomException.class) + .hasMessageContaining(ErrorCode.UNAUTHORIZED_MENTORING.getMessage()); + } + + @Nested + class 멘토가_확인하지_않은_멘토링_개수_조회_테스트 { + + @Test + void 멘토가_확인하지_않은_멘토링_개수를_반환한다() { + // given + mentoringFixture.확인되지_않은_멘토링(mentor1.getId(), menteeUser1.getId()); + mentoringFixture.확인되지_않은_멘토링(mentor1.getId(), menteeUser2.getId()); + mentoringFixture.승인된_멘토링(mentor1.getId(), menteeUser3.getId()); + + // when + MentoringCountResponse response = mentoringCheckService.getUncheckedMentoringCount(mentorUser1.getId()); + + // then + assertThat(response.uncheckedCount()).isEqualTo(2); + } + + @Test + void 멘토가_확인하지_않은_멘토링이_없으면_0을_반환한다() { + // given + mentoringFixture.승인된_멘토링(mentor1.getId(), menteeUser1.getId()); + + // when + MentoringCountResponse response = mentoringCheckService.getUncheckedMentoringCount(mentorUser1.getId()); + + // then + assertThat(response.uncheckedCount()).isZero(); + } } } } diff --git a/src/test/java/com/example/solidconnection/mentor/service/MentoringQueryServiceTest.java b/src/test/java/com/example/solidconnection/mentor/service/MentoringQueryServiceTest.java index 3dbb68466..9fc5700e9 100644 --- a/src/test/java/com/example/solidconnection/mentor/service/MentoringQueryServiceTest.java +++ b/src/test/java/com/example/solidconnection/mentor/service/MentoringQueryServiceTest.java @@ -6,7 +6,8 @@ import com.example.solidconnection.common.dto.SliceResponse; import com.example.solidconnection.mentor.domain.Mentor; import com.example.solidconnection.mentor.domain.Mentoring; -import com.example.solidconnection.mentor.dto.MentoringResponse; +import com.example.solidconnection.mentor.dto.MentoringForMenteeResponse; +import com.example.solidconnection.mentor.dto.MentoringForMentorResponse; import com.example.solidconnection.mentor.fixture.MentorFixture; import com.example.solidconnection.mentor.fixture.MentoringFixture; import com.example.solidconnection.siteuser.domain.SiteUser; @@ -66,10 +67,10 @@ class 멘토의_멘토링_목록_조회_테스트 { Mentoring mentoring3 = mentoringFixture.거절된_멘토링(mentor1.getId(), menteeUser3.getId()); // when - SliceResponse response = mentoringQueryService.getMentoringsForMentor(mentorUser1.getId(), pageable); + SliceResponse response = mentoringQueryService.getMentoringsForMentor(mentorUser1.getId(), pageable); // then - assertThat(response.content()).extracting(MentoringResponse::mentoringId) + assertThat(response.content()).extracting(MentoringForMentorResponse::mentoringId) .containsExactlyInAnyOrder( mentoring1.getId(), mentoring2.getId(), @@ -84,10 +85,10 @@ class 멘토의_멘토링_목록_조회_테스트 { mentoringFixture.승인된_멘토링(mentor1.getId(), menteeUser2.getId()); // when - SliceResponse response = mentoringQueryService.getMentoringsForMentor(mentorUser1.getId(), pageable); + SliceResponse response = mentoringQueryService.getMentoringsForMentor(mentorUser1.getId(), pageable); // then - assertThat(response.content()).extracting(MentoringResponse::nickname) + assertThat(response.content()).extracting(MentoringForMentorResponse::nickname) .containsExactlyInAnyOrder( menteeUser1.getNickname(), menteeUser2.getNickname() @@ -97,7 +98,7 @@ class 멘토의_멘토링_목록_조회_테스트 { @Test void 멘토링이_없는_경우_빈_리스트를_반환한다() { // when - SliceResponse response = mentoringQueryService.getMentoringsForMentor(mentorUser1.getId(), pageable); + SliceResponse response = mentoringQueryService.getMentoringsForMentor(mentorUser1.getId(), pageable); // then assertThat(response.content()).isEmpty(); @@ -115,11 +116,11 @@ class 멘티의_멘토링_목록_조회_테스트 { mentoringFixture.대기중_멘토링(mentor3.getId(), menteeUser1.getId()); // when - SliceResponse response = mentoringQueryService.getMentoringsForMentee( + SliceResponse response = mentoringQueryService.getMentoringsForMentee( menteeUser1.getId(), VerifyStatus.APPROVED, pageable); // then - assertThat(response.content()).extracting(MentoringResponse::mentoringId) + assertThat(response.content()).extracting(MentoringForMenteeResponse::mentoringId) .containsExactlyInAnyOrder( mentoring1.getId(), mentoring2.getId() @@ -134,11 +135,11 @@ class 멘티의_멘토링_목록_조회_테스트 { mentoringFixture.승인된_멘토링(mentor3.getId(), menteeUser1.getId()); // when - SliceResponse response = mentoringQueryService.getMentoringsForMentee( + SliceResponse response = mentoringQueryService.getMentoringsForMentee( menteeUser1.getId(), VerifyStatus.PENDING, pageable); // then - assertThat(response.content()).extracting(MentoringResponse::mentoringId) + assertThat(response.content()).extracting(MentoringForMenteeResponse::mentoringId) .containsExactlyInAnyOrder( mentoring1.getId(), mentoring2.getId() @@ -152,11 +153,11 @@ class 멘티의_멘토링_목록_조회_테스트 { mentoringFixture.승인된_멘토링(mentor2.getId(), menteeUser1.getId()); // when - SliceResponse response = mentoringQueryService.getMentoringsForMentee( + SliceResponse response = mentoringQueryService.getMentoringsForMentee( menteeUser1.getId(), VerifyStatus.APPROVED, pageable); // then - assertThat(response.content()).extracting(MentoringResponse::nickname) + assertThat(response.content()).extracting(MentoringForMenteeResponse::nickname) .containsExactlyInAnyOrder( mentorUser1.getNickname(), mentorUser2.getNickname() @@ -166,7 +167,8 @@ class 멘티의_멘토링_목록_조회_테스트 { @Test void 멘토링이_없는_경우_빈_리스트를_반환한다() { // when - SliceResponse response = mentoringQueryService.getMentoringsForMentor(mentorUser1.getId(), pageable); + SliceResponse response = mentoringQueryService.getMentoringsForMentee( + mentorUser1.getId(), VerifyStatus.APPROVED, pageable); // then assertThat(response.content()).isEmpty(); From 3fb17e7a7f73036ec13031610f67c2039f1ca4b8 Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Sat, 2 Aug 2025 02:21:43 +0900 Subject: [PATCH 7/9] =?UTF-8?q?test:=20=EB=A9=98=ED=86=A0=EB=A7=81=20?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D=20=EC=A1=B0=ED=9A=8C=20=EC=8B=9C,=20?= =?UTF-8?q?=ED=99=95=EC=9D=B8=EC=97=AC=EB=B6=80=20=ED=8F=AC=ED=95=A8=20?= =?UTF-8?q?=EA=B2=80=EC=A6=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/MentoringQueryServiceTest.java | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/src/test/java/com/example/solidconnection/mentor/service/MentoringQueryServiceTest.java b/src/test/java/com/example/solidconnection/mentor/service/MentoringQueryServiceTest.java index 9fc5700e9..2851f8ab4 100644 --- a/src/test/java/com/example/solidconnection/mentor/service/MentoringQueryServiceTest.java +++ b/src/test/java/com/example/solidconnection/mentor/service/MentoringQueryServiceTest.java @@ -1,6 +1,7 @@ package com.example.solidconnection.mentor.service; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.AssertionsForClassTypes.tuple; import com.example.solidconnection.common.VerifyStatus; import com.example.solidconnection.common.dto.SliceResponse; @@ -10,6 +11,7 @@ import com.example.solidconnection.mentor.dto.MentoringForMentorResponse; import com.example.solidconnection.mentor.fixture.MentorFixture; import com.example.solidconnection.mentor.fixture.MentoringFixture; +import com.example.solidconnection.mentor.repository.MentoringRepository; import com.example.solidconnection.siteuser.domain.SiteUser; import com.example.solidconnection.siteuser.fixture.SiteUserFixture; import com.example.solidconnection.support.TestContainerSpringBootTest; @@ -37,6 +39,9 @@ class MentoringQueryServiceTest { @Autowired private MentoringFixture mentoringFixture; + @Autowired + private MentoringRepository mentoringRepository; + private SiteUser mentorUser1, mentorUser2; private SiteUser menteeUser1, menteeUser2, menteeUser3; private Mentor mentor1, mentor2, mentor3; @@ -95,6 +100,23 @@ class 멘토의_멘토링_목록_조회_테스트 { ); } + @Test + void 멘토링_확인_여부를_포함한다() { + // given + Mentoring mentoring1 = mentoringFixture.대기중_멘토링(mentor1.getId(), menteeUser1.getId()); + Mentoring mentoring2 = mentoringFixture.승인된_멘토링(mentor1.getId(), menteeUser2.getId()); + // when + SliceResponse response = mentoringQueryService.getMentoringsForMentor(mentorUser1.getId(), pageable); + + // then + assertThat(response.content()) + .extracting(MentoringForMentorResponse::mentoringId, MentoringForMentorResponse::isChecked) + .containsExactlyInAnyOrder( + tuple(mentoring1.getId(), false), + tuple(mentoring2.getId(), true) + ); + } + @Test void 멘토링이_없는_경우_빈_리스트를_반환한다() { // when @@ -164,6 +186,27 @@ class 멘티의_멘토링_목록_조회_테스트 { ); } + @Test + void 멘토링_확인_여부를_포함한다() { + // given + Mentoring mentoring1 = mentoringFixture.대기중_멘토링(mentor1.getId(), menteeUser1.getId()); + Mentoring mentoring2 = mentoringFixture.대기중_멘토링(mentor2.getId(), menteeUser1.getId()); + mentoring1.checkByMentee(); + mentoringRepository.save(mentoring1); + + // when + SliceResponse response = mentoringQueryService.getMentoringsForMentee( + menteeUser1.getId(), VerifyStatus.PENDING, pageable); + + // then + assertThat(response.content()) + .extracting(MentoringForMenteeResponse::mentoringId, MentoringForMenteeResponse::isChecked) + .containsExactlyInAnyOrder( + tuple(mentoring1.getId(), true), + tuple(mentoring2.getId(), false) + ); + } + @Test void 멘토링이_없는_경우_빈_리스트를_반환한다() { // when From abe76d047361fab84ae2a762d59cf6d31e9f12c7 Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Sat, 2 Aug 2025 02:37:04 +0900 Subject: [PATCH 8/9] =?UTF-8?q?refactor:=20=EB=A9=98=ED=86=A0=EA=B0=80=20?= =?UTF-8?q?=EC=8A=B9=EC=9D=B8=ED=95=98=EB=A9=B4,=20=EB=A9=98=ED=8B=B0?= =?UTF-8?q?=EC=9D=98=20=EB=A9=98=ED=86=A0=EB=A7=81=20=ED=99=95=EC=9D=B8?= =?UTF-8?q?=EC=83=81=ED=83=9C=20=EC=B4=88=EA=B8=B0=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/example/solidconnection/mentor/domain/Mentoring.java | 3 +++ .../mentor/service/MentoringCommandServiceTest.java | 1 + 2 files changed, 4 insertions(+) diff --git a/src/main/java/com/example/solidconnection/mentor/domain/Mentoring.java b/src/main/java/com/example/solidconnection/mentor/domain/Mentoring.java index 0eb0949a5..ead13132b 100644 --- a/src/main/java/com/example/solidconnection/mentor/domain/Mentoring.java +++ b/src/main/java/com/example/solidconnection/mentor/domain/Mentoring.java @@ -73,6 +73,9 @@ public void confirm(VerifyStatus status) { if (this.checkedAtByMentor == null) { this.checkedAtByMentor = this.confirmedAt; } + if (this.checkedAtByMentee != null) { + this.checkedAtByMentee = null; + } } public void checkByMentor() { diff --git a/src/test/java/com/example/solidconnection/mentor/service/MentoringCommandServiceTest.java b/src/test/java/com/example/solidconnection/mentor/service/MentoringCommandServiceTest.java index 2a731a8b5..a92925653 100644 --- a/src/test/java/com/example/solidconnection/mentor/service/MentoringCommandServiceTest.java +++ b/src/test/java/com/example/solidconnection/mentor/service/MentoringCommandServiceTest.java @@ -110,6 +110,7 @@ class 멘토링_승인_거절_테스트 { () -> assertThat(confirmedMentoring.getVerifyStatus()).isEqualTo(VerifyStatus.APPROVED), () -> assertThat(confirmedMentoring.getConfirmedAt()).isNotNull(), () -> assertThat(confirmedMentoring.getCheckedAtByMentor()).isNotNull(), + () -> assertThat(confirmedMentoring.getCheckedAtByMentee()).isNull(), () -> assertThat(mentor.getMenteeCount()).isEqualTo(beforeMenteeCount + 1) ); } From 09ee5b3b4c8bb7397037eaa97769b2f320b08cef Mon Sep 17 00:00:00 2001 From: nayonsoso Date: Sat, 2 Aug 2025 02:43:33 +0900 Subject: [PATCH 9/9] =?UTF-8?q?refactor:=20=EB=A9=98=ED=8B=B0=EA=B0=80=20?= =?UTF-8?q?=EA=B1=B0=EC=A0=88=EB=90=9C=20=EB=A9=98=ED=86=A0=EB=A7=81=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=ED=95=98=EC=A7=80=20=EB=AA=BB=ED=95=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mentor/service/MentoringQueryService.java | 4 ++++ .../mentor/service/MentoringQueryServiceTest.java | 15 +++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/src/main/java/com/example/solidconnection/mentor/service/MentoringQueryService.java b/src/main/java/com/example/solidconnection/mentor/service/MentoringQueryService.java index 30349004d..bb9deafe0 100644 --- a/src/main/java/com/example/solidconnection/mentor/service/MentoringQueryService.java +++ b/src/main/java/com/example/solidconnection/mentor/service/MentoringQueryService.java @@ -5,6 +5,7 @@ import com.example.solidconnection.common.VerifyStatus; import com.example.solidconnection.common.dto.SliceResponse; import com.example.solidconnection.common.exception.CustomException; +import com.example.solidconnection.common.exception.ErrorCode; import com.example.solidconnection.mentor.domain.Mentor; import com.example.solidconnection.mentor.domain.Mentoring; import com.example.solidconnection.mentor.dto.MentoringForMenteeResponse; @@ -37,6 +38,9 @@ public class MentoringQueryService { public SliceResponse getMentoringsForMentee( long siteUserId, VerifyStatus verifyStatus, Pageable pageable ) { + if (verifyStatus == VerifyStatus.REJECTED) { + throw new CustomException(ErrorCode.UNAUTHORIZED_MENTORING, "거절된 멘토링은 조회할 수 없습니다."); + } Slice mentoringSlice = mentoringRepository.findAllByMenteeIdAndVerifyStatus(siteUserId, verifyStatus, pageable); List mentorings = mentoringSlice.toList(); diff --git a/src/test/java/com/example/solidconnection/mentor/service/MentoringQueryServiceTest.java b/src/test/java/com/example/solidconnection/mentor/service/MentoringQueryServiceTest.java index 2851f8ab4..d8146dc51 100644 --- a/src/test/java/com/example/solidconnection/mentor/service/MentoringQueryServiceTest.java +++ b/src/test/java/com/example/solidconnection/mentor/service/MentoringQueryServiceTest.java @@ -1,10 +1,13 @@ package com.example.solidconnection.mentor.service; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.AssertionsForClassTypes.tuple; import com.example.solidconnection.common.VerifyStatus; import com.example.solidconnection.common.dto.SliceResponse; +import com.example.solidconnection.common.exception.CustomException; +import com.example.solidconnection.common.exception.ErrorCode; import com.example.solidconnection.mentor.domain.Mentor; import com.example.solidconnection.mentor.domain.Mentoring; import com.example.solidconnection.mentor.dto.MentoringForMenteeResponse; @@ -105,6 +108,7 @@ class 멘토의_멘토링_목록_조회_테스트 { // given Mentoring mentoring1 = mentoringFixture.대기중_멘토링(mentor1.getId(), menteeUser1.getId()); Mentoring mentoring2 = mentoringFixture.승인된_멘토링(mentor1.getId(), menteeUser2.getId()); + // when SliceResponse response = mentoringQueryService.getMentoringsForMentor(mentorUser1.getId(), pageable); @@ -130,6 +134,17 @@ class 멘토의_멘토링_목록_조회_테스트 { @Nested class 멘티의_멘토링_목록_조회_테스트 { + @Test + void 거절된_멘토링_목록을_조회하면_예외가_발생한다() { + // given + mentoringFixture.거절된_멘토링(mentor1.getId(), menteeUser1.getId()); + + // when & then + assertThatCode(() -> mentoringQueryService.getMentoringsForMentee(menteeUser1.getId(), VerifyStatus.REJECTED, pageable)) + .isInstanceOf(CustomException.class) + .hasMessageContaining(ErrorCode.UNAUTHORIZED_MENTORING.getMessage()); + } + @Test void 승인된_멘토링_목록을_조회한다() { // given