diff --git a/back/src/main/java/com/back/domain/member/member/service/MemberStorage.java b/back/src/main/java/com/back/domain/member/member/service/MemberStorage.java index 3c5f4001..c7d44a1c 100644 --- a/back/src/main/java/com/back/domain/member/member/service/MemberStorage.java +++ b/back/src/main/java/com/back/domain/member/member/service/MemberStorage.java @@ -24,12 +24,12 @@ public Mentor findMentorByMember(Member member) { } public Mentor findMentorByMemberId(Long memberId) { - return mentorRepository.findByMemberId(memberId) + return mentorRepository.findByMemberIdWithMember(memberId) .orElseThrow(() -> new ServiceException(MemberErrorCode.NOT_FOUND_MENTOR)); } public Mentee findMenteeByMember(Member member) { - return menteeRepository.findByMemberId(member.getId()) + return menteeRepository.findByMemberIdWithMember(member.getId()) .orElseThrow(() -> new ServiceException(MemberErrorCode.NOT_FOUND_MENTEE)); } diff --git a/back/src/main/java/com/back/domain/member/mentee/dto/MenteeDto.java b/back/src/main/java/com/back/domain/member/mentee/dto/MenteeDto.java index b28031a8..a6f837bd 100644 --- a/back/src/main/java/com/back/domain/member/mentee/dto/MenteeDto.java +++ b/back/src/main/java/com/back/domain/member/mentee/dto/MenteeDto.java @@ -6,13 +6,13 @@ public record MenteeDto( @Schema(description = "멘티 ID") Long menteeId, - @Schema(description = "멘티명") - String name + @Schema(description = "멘티 닉네임") + String nickname ) { public static MenteeDto from(Mentee mentee) { return new MenteeDto( mentee.getId(), - mentee.getMember().getName() + mentee.getMember().getNickname() ); } } diff --git a/back/src/main/java/com/back/domain/member/mentee/repository/MenteeRepository.java b/back/src/main/java/com/back/domain/member/mentee/repository/MenteeRepository.java index 4fece262..2f93199f 100644 --- a/back/src/main/java/com/back/domain/member/mentee/repository/MenteeRepository.java +++ b/back/src/main/java/com/back/domain/member/mentee/repository/MenteeRepository.java @@ -12,6 +12,9 @@ public interface MenteeRepository extends JpaRepository { @Query("SELECT m FROM Mentee m WHERE m.member.id = :memberId AND m.isDeleted = false") Optional findByMemberId(@Param("memberId") Long memberId); + @Query("SELECT m FROM Mentee m JOIN FETCH m.member WHERE m.member.id = :memberId AND m.isDeleted = false") + Optional findByMemberIdWithMember(@Param("memberId") Long memberId); + @Query("SELECT m FROM Mentee m WHERE m.id = :id AND m.isDeleted = false") Optional findById(@Param("id") Long id); diff --git a/back/src/main/java/com/back/domain/member/mentor/dto/MentorDetailDto.java b/back/src/main/java/com/back/domain/member/mentor/dto/MentorDetailDto.java index 59cfebf6..4c4e27c0 100644 --- a/back/src/main/java/com/back/domain/member/mentor/dto/MentorDetailDto.java +++ b/back/src/main/java/com/back/domain/member/mentor/dto/MentorDetailDto.java @@ -6,8 +6,8 @@ public record MentorDetailDto( @Schema(description = "멘토 ID") Long mentorId, - @Schema(description = "멘토명") - String name, + @Schema(description = "멘토 닉네임") + String nickname, @Schema(description = "평점") Double rate, // TODO: Job id, name @@ -17,7 +17,7 @@ public record MentorDetailDto( public static MentorDetailDto from(Mentor mentor) { return new MentorDetailDto( mentor.getId(), - mentor.getMember().getName(), + mentor.getMember().getNickname(), mentor.getRate(), mentor.getCareerYears() ); diff --git a/back/src/main/java/com/back/domain/member/mentor/dto/MentorDto.java b/back/src/main/java/com/back/domain/member/mentor/dto/MentorDto.java index e76575b9..d25fb2ec 100644 --- a/back/src/main/java/com/back/domain/member/mentor/dto/MentorDto.java +++ b/back/src/main/java/com/back/domain/member/mentor/dto/MentorDto.java @@ -6,13 +6,13 @@ public record MentorDto( @Schema(description = "멘토 ID") Long mentorId, - @Schema(description = "멘토명") - String name + @Schema(description = "멘토 닉네임") + String nickname ) { public static MentorDto from(Mentor mentor) { return new MentorDto( mentor.getId(), - mentor.getMember().getName() + mentor.getMember().getNickname() ); } } diff --git a/back/src/main/java/com/back/domain/member/mentor/repository/MentorRepository.java b/back/src/main/java/com/back/domain/member/mentor/repository/MentorRepository.java index 14dcfeaf..db994c93 100644 --- a/back/src/main/java/com/back/domain/member/mentor/repository/MentorRepository.java +++ b/back/src/main/java/com/back/domain/member/mentor/repository/MentorRepository.java @@ -12,6 +12,9 @@ public interface MentorRepository extends JpaRepository { @Query("SELECT m FROM Mentor m WHERE m.member.id = :memberId AND m.isDeleted = false") Optional findByMemberId(@Param("memberId") Long memberId); + @Query("SELECT m FROM Mentor m JOIN FETCH m.member WHERE m.member.id = :memberId AND m.isDeleted = false") + Optional findByMemberIdWithMember(@Param("memberId") Long memberId); + @Query("SELECT m FROM Mentor m WHERE m.id = :id AND m.isDeleted = false") Optional findById(@Param("id") Long id); diff --git a/back/src/main/java/com/back/domain/mentoring/mentoring/repository/MentoringRepositoryImpl.java b/back/src/main/java/com/back/domain/mentoring/mentoring/repository/MentoringRepositoryImpl.java index 18e1ecb8..04ac9a3f 100644 --- a/back/src/main/java/com/back/domain/mentoring/mentoring/repository/MentoringRepositoryImpl.java +++ b/back/src/main/java/com/back/domain/mentoring/mentoring/repository/MentoringRepositoryImpl.java @@ -26,11 +26,11 @@ public Page searchMentorings(String keyword, Pageable pageable) { BooleanBuilder builder = new BooleanBuilder(); - // 제목, 멘토 이름 검색 조건 + // 제목, 멘토 닉네임 검색 조건 if (keyword != null && !keyword.isBlank()) { builder.and( mentoring.title.containsIgnoreCase(keyword) - .or(mentor.member.name.containsIgnoreCase(keyword)) + .or(mentor.member.nickname.containsIgnoreCase(keyword)) ); } diff --git a/back/src/main/java/com/back/domain/mentoring/slot/dto/MentorSlotDetailDto.java b/back/src/main/java/com/back/domain/mentoring/slot/dto/MentorSlotDetailDto.java new file mode 100644 index 00000000..a751ae51 --- /dev/null +++ b/back/src/main/java/com/back/domain/mentoring/slot/dto/MentorSlotDetailDto.java @@ -0,0 +1,33 @@ +package com.back.domain.mentoring.slot.dto; + +import com.back.domain.mentoring.slot.constant.MentorSlotStatus; +import com.back.domain.mentoring.slot.entity.MentorSlot; +import io.swagger.v3.oas.annotations.media.Schema; + +import java.time.LocalDateTime; + +public record MentorSlotDetailDto( + @Schema(description = "멘토 슬롯 ID") + Long mentorSlotId, + @Schema(description = "시작 일시") + LocalDateTime startDateTime, + @Schema(description = "종료 일시") + LocalDateTime endDateTime, + @Schema(description = "멘토 슬롯 상태") + MentorSlotStatus mentorSlotStatus, + @Schema(description = "생성일") + LocalDateTime createDate, + @Schema(description = "수정일") + LocalDateTime modifyDate +) { + public static MentorSlotDetailDto from(MentorSlot mentorSlot) { + return new MentorSlotDetailDto( + mentorSlot.getId(), + mentorSlot.getStartDateTime(), + mentorSlot.getEndDateTime(), + mentorSlot.getStatus(), + mentorSlot.getCreateDate(), + mentorSlot.getModifyDate() + ); + } +} diff --git a/back/src/main/java/com/back/domain/mentoring/slot/dto/response/MentorSlotResponse.java b/back/src/main/java/com/back/domain/mentoring/slot/dto/response/MentorSlotResponse.java index 8106144a..0d8bde2f 100644 --- a/back/src/main/java/com/back/domain/mentoring/slot/dto/response/MentorSlotResponse.java +++ b/back/src/main/java/com/back/domain/mentoring/slot/dto/response/MentorSlotResponse.java @@ -1,51 +1,21 @@ package com.back.domain.mentoring.slot.dto.response; +import com.back.domain.member.mentor.dto.MentorDto; +import com.back.domain.mentoring.mentoring.dto.MentoringDto; import com.back.domain.mentoring.mentoring.entity.Mentoring; -import com.back.domain.mentoring.slot.constant.MentorSlotStatus; +import com.back.domain.mentoring.slot.dto.MentorSlotDetailDto; import com.back.domain.mentoring.slot.entity.MentorSlot; -import io.swagger.v3.oas.annotations.media.Schema; - -import java.time.LocalDateTime; public record MentorSlotResponse( - @Schema(description = "멘토 슬롯 ID") - Long mentorSlotId, - - @Schema(description = "멘토 ID") - Long mentorId, - - @Schema(description = "멘토링 ID") - Long mentoringId, - - @Schema(description = "멘토링 제목") - String mentoringTitle, - - @Schema(description = "시작 일시") - LocalDateTime startDateTime, - - @Schema(description = "종료 일시") - LocalDateTime endDateTime, - - @Schema(description = "멘토 슬롯 상태") - MentorSlotStatus mentorSlotStatus, - - @Schema(description = "생성일") - LocalDateTime createDate, - - @Schema(description = "수정일") - LocalDateTime modifyDate + MentorSlotDetailDto mentorSlot, + MentorDto mentor, + MentoringDto mentoring ) { public static MentorSlotResponse from(MentorSlot mentorSlot, Mentoring mentoring) { return new MentorSlotResponse( - mentorSlot.getId(), - mentorSlot.getMentor().getId(), - mentoring.getId(), - mentoring.getTitle(), - mentorSlot.getStartDateTime(), - mentorSlot.getEndDateTime(), - mentorSlot.getStatus(), - mentorSlot.getCreateDate(), - mentorSlot.getModifyDate() + MentorSlotDetailDto.from(mentorSlot), + MentorDto.from(mentorSlot.getMentor()), + MentoringDto.from(mentoring) ); } } diff --git a/back/src/main/java/com/back/domain/mentoring/slot/service/DateTimeValidator.java b/back/src/main/java/com/back/domain/mentoring/slot/service/DateTimeValidator.java index cbeb4ead..c0a193ef 100644 --- a/back/src/main/java/com/back/domain/mentoring/slot/service/DateTimeValidator.java +++ b/back/src/main/java/com/back/domain/mentoring/slot/service/DateTimeValidator.java @@ -4,7 +4,9 @@ import com.back.global.exception.ServiceException; import java.time.Duration; +import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.LocalTime; public class DateTimeValidator { @@ -50,4 +52,16 @@ public static void validateTimeSlot(LocalDateTime start, LocalDateTime end) { validateStartTimeNotInPast(start); validateMinimumDuration(start, end); } + + public static void validateRepetitionSlot(LocalDate startDate, LocalTime startTime, + LocalDate endDate, LocalTime endTime) { + if (endDate.isBefore(startDate)) { + throw new ServiceException(MentorSlotErrorCode.END_TIME_BEFORE_START); + } + + LocalDateTime startDateTime = LocalDateTime.of(startDate, startTime); + LocalDateTime endDateTime = LocalDateTime.of(startDate, endTime); + + validateTimeSlot(startDateTime, endDateTime); + } } diff --git a/back/src/main/java/com/back/domain/mentoring/slot/service/MentorSlotService.java b/back/src/main/java/com/back/domain/mentoring/slot/service/MentorSlotService.java index 32fe56ca..068a7f04 100644 --- a/back/src/main/java/com/back/domain/mentoring/slot/service/MentorSlotService.java +++ b/back/src/main/java/com/back/domain/mentoring/slot/service/MentorSlotService.java @@ -80,6 +80,9 @@ public MentorSlotResponse createMentorSlot(MentorSlotRequest reqDto, Mentor ment public void createMentorSlotRepetition(MentorSlotRepetitionRequest reqDto, Mentor mentor) { List mentorSlots = new ArrayList<>(); + DateTimeValidator.validateRepetitionSlot(reqDto.repeatStartDate(), reqDto.startTime(), + reqDto.repeatEndDate(), reqDto.endTime()); + // 지정한 요일별로 슬롯 목록 생성 for(DayOfWeek targetDayOfWeek : reqDto.daysOfWeek()) { mentorSlots.addAll(generateSlotsForDayOfWeek(reqDto, targetDayOfWeek, mentor)); diff --git a/back/src/main/java/com/back/global/converter/StringListConverter.java b/back/src/main/java/com/back/global/converter/StringListConverter.java index 099a6385..07adf28a 100644 --- a/back/src/main/java/com/back/global/converter/StringListConverter.java +++ b/back/src/main/java/com/back/global/converter/StringListConverter.java @@ -1,23 +1,52 @@ package com.back.global.converter; -import com.back.standard.util.Ut; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.persistence.AttributeConverter; import jakarta.persistence.Converter; import org.springframework.stereotype.Component; +import java.util.ArrayList; import java.util.List; @Converter @Component public class StringListConverter implements AttributeConverter, String> { + private static final ObjectMapper objectMapper = new ObjectMapper(); + @Override public String convertToDatabaseColumn(List attribute) { - return attribute == null ? null : Ut.json.toString(attribute); + if (attribute == null || attribute.isEmpty()) { + return null; + } + try { + return objectMapper.writeValueAsString(attribute); + } catch (JsonProcessingException e) { + throw new IllegalArgumentException("JSON 변환 실패", e); + } } @Override public List convertToEntityAttribute(String dbData) { - return Ut.json.toList(dbData, String.class); + if (dbData == null || dbData.trim().isEmpty()) { + return new ArrayList<>(); + } + try { + // 이중 인코딩된 경우 처리 + String data = dbData; + if (data.startsWith("\"") && data.endsWith("\"")) { + data = objectMapper.readValue(data, String.class); + } + + return objectMapper.readValue( + data, + objectMapper.getTypeFactory().constructCollectionType(List.class, String.class) + ); + } catch (JsonProcessingException e) { + System.err.println("JSON 파싱 실패. 원본 데이터: " + dbData); + e.printStackTrace(); + return new ArrayList<>(); + } } } diff --git a/back/src/test/java/com/back/domain/mentoring/mentoring/controller/MentoringControllerTest.java b/back/src/test/java/com/back/domain/mentoring/mentoring/controller/MentoringControllerTest.java index 78a14784..df0e0419 100644 --- a/back/src/test/java/com/back/domain/mentoring/mentoring/controller/MentoringControllerTest.java +++ b/back/src/test/java/com/back/domain/mentoring/mentoring/controller/MentoringControllerTest.java @@ -21,6 +21,7 @@ import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.http.MediaType; +import org.springframework.test.context.ActiveProfiles; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.ResultActions; import org.springframework.transaction.annotation.Transactional; @@ -33,6 +34,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; +@ActiveProfiles("test") @SpringBootTest @AutoConfigureMockMvc @Transactional @@ -75,14 +77,15 @@ void setUp() { void getMentoringsSuccess() throws Exception { mentoringFixture.createMentorings(mentor, 15); - // TODO: 일반 조회, 목록 조회는 쿠키 없어도 가능하게 설정 필요 performGetMentorings(null, "0") .andExpect(jsonPath("$.data.mentorings").isArray()) .andExpect(jsonPath("$.data.mentorings.length()").value(10)) .andExpect(jsonPath("$.data.currentPage").value(0)) .andExpect(jsonPath("$.data.totalPage").value(2)) .andExpect(jsonPath("$.data.totalElements").value(15)) - .andExpect(jsonPath("$.data.hasNext").value(true)); + .andExpect(jsonPath("$.data.hasNext").value(true)) + .andExpect(jsonPath("$.data.mentorings[0].tags[0]").value("Spring")) + .andExpect(jsonPath("$.data.mentorings[0].tags[1]").value("Java")); } @Test @@ -118,7 +121,7 @@ void getMentoringsSuccessSearchMentor() throws Exception { mentoringFixture.createMentorings(mentor, 8); mentoringFixture.createMentorings(mentor2, 3); - performGetMentorings(mentorMember.getName(), "0") + performGetMentorings(mentorMember.getNickname(), "0") .andExpect(jsonPath("$.data.mentorings").isArray()) .andExpect(jsonPath("$.data.mentorings.length()").value(3)) .andExpect(jsonPath("$.data.currentPage").value(0)) @@ -162,7 +165,9 @@ void getMentoringSuccess() throws Exception { .andExpect(handler().methodName("getMentoring")) .andExpect(status().isOk()) .andExpect(jsonPath("$.resultCode").value("200")) - .andExpect(jsonPath("$.msg").value("멘토링을 조회하였습니다.")); + .andExpect(jsonPath("$.msg").value("멘토링을 조회하였습니다.")) + .andExpect(jsonPath("$.data.mentoring.tags[0]").value("Spring")) + .andExpect(jsonPath("$.data.mentoring.tags[1]").value("Java")); } @@ -193,7 +198,7 @@ void createMentoringSuccess() throws Exception { // Mentor 정보 검증 .andExpect(jsonPath("$.data.mentor.mentorId").value(mentorOfMentoring.getId())) - .andExpect(jsonPath("$.data.mentor.name").value(mentorOfMentoring.getMember().getName())) + .andExpect(jsonPath("$.data.mentor.nickname").value(mentorOfMentoring.getMember().getNickname())) .andExpect(jsonPath("$.data.mentor.rate").value(mentorOfMentoring.getRate())) .andExpect(jsonPath("$.data.mentor.careerYears").value(mentorOfMentoring.getCareerYears())); } diff --git a/back/src/test/java/com/back/domain/mentoring/slot/controller/MentorSlotControllerTest.java b/back/src/test/java/com/back/domain/mentoring/slot/controller/MentorSlotControllerTest.java index 3412ecaf..4bbc18fd 100644 --- a/back/src/test/java/com/back/domain/mentoring/slot/controller/MentorSlotControllerTest.java +++ b/back/src/test/java/com/back/domain/mentoring/slot/controller/MentorSlotControllerTest.java @@ -18,6 +18,7 @@ import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.http.MediaType; +import org.springframework.test.context.ActiveProfiles; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.ResultActions; import org.springframework.transaction.annotation.Transactional; @@ -35,7 +36,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; - +@ActiveProfiles("test") @SpringBootTest @AutoConfigureMockMvc @Transactional @@ -160,13 +161,13 @@ void getMentorSlotSuccess() throws Exception { .andExpect(handler().methodName("getMentorSlot")) .andExpect(jsonPath("$.resultCode").value("200")) .andExpect(jsonPath("$.msg").value("멘토의 예약 가능 일정을 조회하였습니다.")) - .andExpect(jsonPath("$.data.mentorSlotId").value(mentorSlot.getId())) - .andExpect(jsonPath("$.data.mentorId").value(mentorSlot.getMentor().getId())) - .andExpect(jsonPath("$.data.mentoringId").value(mentoring.getId())) - .andExpect(jsonPath("$.data.mentoringTitle").value(mentoring.getTitle())) - .andExpect(jsonPath("$.data.startDateTime").value(mentorSlot.getStartDateTime().format(formatter))) - .andExpect(jsonPath("$.data.endDateTime").value(mentorSlot.getEndDateTime().format(formatter))) - .andExpect(jsonPath("$.data.mentorSlotStatus").value(mentorSlot.getStatus().name())); + .andExpect(jsonPath("$.data.mentorSlot.mentorSlotId").value(mentorSlot.getId())) + .andExpect(jsonPath("$.data.mentor.mentorId").value(mentorSlot.getMentor().getId())) + .andExpect(jsonPath("$.data.mentoring.mentoringId").value(mentoring.getId())) + .andExpect(jsonPath("$.data.mentoring.title").value(mentoring.getTitle())) + .andExpect(jsonPath("$.data.mentorSlot.startDateTime").value(mentorSlot.getStartDateTime().format(formatter))) + .andExpect(jsonPath("$.data.mentorSlot.endDateTime").value(mentorSlot.getEndDateTime().format(formatter))) + .andExpect(jsonPath("$.data.mentorSlot.mentorSlotStatus").value(mentorSlot.getStatus().name())); } // ===== 슬롯 생성 ===== @@ -186,13 +187,13 @@ void createMentorSlotSuccess() throws Exception { .orElseThrow(() -> new ServiceException(MentorSlotErrorCode.NOT_FOUND_MENTOR_SLOT)); resultActions - .andExpect(jsonPath("$.data.mentorSlotId").value(mentorSlot.getId())) - .andExpect(jsonPath("$.data.mentorId").value(mentorSlot.getMentor().getId())) - .andExpect(jsonPath("$.data.mentoringId").value(mentoring.getId())) - .andExpect(jsonPath("$.data.mentoringTitle").value(mentoring.getTitle())) - .andExpect(jsonPath("$.data.startDateTime").value(startDateTime)) - .andExpect(jsonPath("$.data.endDateTime").value(endDateTime)) - .andExpect(jsonPath("$.data.mentorSlotStatus").value("AVAILABLE")); + .andExpect(jsonPath("$.data.mentorSlot.mentorSlotId").value(mentorSlot.getId())) + .andExpect(jsonPath("$.data.mentor.mentorId").value(mentorSlot.getMentor().getId())) + .andExpect(jsonPath("$.data.mentoring.mentoringId").value(mentoring.getId())) + .andExpect(jsonPath("$.data.mentoring.title").value(mentoring.getTitle())) + .andExpect(jsonPath("$.data.mentorSlot.startDateTime").value(startDateTime)) + .andExpect(jsonPath("$.data.mentorSlot.endDateTime").value(endDateTime)) + .andExpect(jsonPath("$.data.mentorSlot.mentorSlotStatus").value("AVAILABLE")); } @Test @@ -288,12 +289,12 @@ void updateMentorSlotSuccess() throws Exception { .andExpect(status().isOk()) .andExpect(jsonPath("$.resultCode").value("200")) .andExpect(jsonPath("$.msg").value("멘토의 예약 가능 일정이 수정되었습니다.")) - .andExpect(jsonPath("$.data.mentorSlotId").value(mentorSlot.getId())) - .andExpect(jsonPath("$.data.mentorId").value(mentorSlot.getMentor().getId())) - .andExpect(jsonPath("$.data.mentoringId").value(mentoring.getId())) - .andExpect(jsonPath("$.data.mentoringTitle").value(mentoring.getTitle())) - .andExpect(jsonPath("$.data.endDateTime").value(expectedEndDate)) - .andExpect(jsonPath("$.data.mentorSlotStatus").value("AVAILABLE")); + .andExpect(jsonPath("$.data.mentorSlot.mentorSlotId").value(mentorSlot.getId())) + .andExpect(jsonPath("$.data.mentor.mentorId").value(mentorSlot.getMentor().getId())) + .andExpect(jsonPath("$.data.mentoring.mentoringId").value(mentoring.getId())) + .andExpect(jsonPath("$.data.mentoring.title").value(mentoring.getTitle())) + .andExpect(jsonPath("$.data.mentorSlot.endDateTime").value(expectedEndDate)) + .andExpect(jsonPath("$.data.mentorSlot.mentorSlotStatus").value("AVAILABLE")); } diff --git a/back/src/test/java/com/back/domain/mentoring/slot/service/DateTimeValidatorTest.java b/back/src/test/java/com/back/domain/mentoring/slot/service/DateTimeValidatorTest.java index 7080cfbc..446a4aee 100644 --- a/back/src/test/java/com/back/domain/mentoring/slot/service/DateTimeValidatorTest.java +++ b/back/src/test/java/com/back/domain/mentoring/slot/service/DateTimeValidatorTest.java @@ -5,7 +5,9 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.LocalTime; import static org.junit.jupiter.api.Assertions.*; @@ -146,4 +148,32 @@ void validateTimeSlot_fail_nullCheck() { assertEquals(MentorSlotErrorCode.START_TIME_REQUIRED.getCode(), exception.getResultCode()); } + + @Test + @DisplayName("반복 일정 정상 케이스") + void validateRepetitionSlot_success() { + LocalDate startDate = LocalDate.now().plusDays(1); + LocalDate endDate = startDate.plusDays(3); + LocalTime startTime = LocalTime.of(10, 0); + LocalTime endTime = LocalTime.of(11, 0); + + assertDoesNotThrow(() -> + DateTimeValidator.validateRepetitionSlot(startDate, startTime, endDate, endTime) + ); + } + + @Test + @DisplayName("반복 종료일이 시작일보다 이전이면 예외 발생") + void validateRepetitionSlot_fail_endDateBeforeStartDate() { + LocalDate startDate = LocalDate.now().plusDays(3); + LocalDate endDate = LocalDate.now().plusDays(1); + LocalTime startTime = LocalTime.of(10, 0); + LocalTime endTime = LocalTime.of(11, 0); + + ServiceException exception = assertThrows(ServiceException.class, + () -> DateTimeValidator.validateRepetitionSlot(startDate, startTime, endDate, endTime) + ); + + assertEquals(MentorSlotErrorCode.END_TIME_BEFORE_START.getCode(), exception.getResultCode()); + } } \ No newline at end of file diff --git a/back/src/test/java/com/back/domain/mentoring/slot/service/MentorSlotServiceTest.java b/back/src/test/java/com/back/domain/mentoring/slot/service/MentorSlotServiceTest.java index e93c1f2f..8cfc7b2f 100644 --- a/back/src/test/java/com/back/domain/mentoring/slot/service/MentorSlotServiceTest.java +++ b/back/src/test/java/com/back/domain/mentoring/slot/service/MentorSlotServiceTest.java @@ -174,8 +174,8 @@ void getMentorSlot() { // then assertThat(result).isNotNull(); - assertThat(result.mentorSlotId()).isEqualTo(slotId); - assertThat(result.mentorId()).isEqualTo(mentor1.getId()); + assertThat(result.mentorSlot().mentorSlotId()).isEqualTo(slotId); + assertThat(result.mentor().mentorId()).isEqualTo(mentor1.getId()); verify(mentoringStorage).findMentorSlot(slotId); verify(mentoringStorage).findMentoringByMentor(mentor1); } @@ -211,12 +211,12 @@ void createMentorSlot() { // then assertThat(result).isNotNull(); - assertThat(result.mentorId()).isEqualTo(mentor1.getId()); - assertThat(result.mentoringId()).isEqualTo(mentoring1.getId()); - assertThat(result.mentoringTitle()).isEqualTo(mentoring1.getTitle()); - assertThat(result.startDateTime()).isEqualTo(request.startDateTime()); - assertThat(result.endDateTime()).isEqualTo(request.endDateTime()); - assertThat(result.mentorSlotStatus()).isEqualTo(MentorSlotStatus.AVAILABLE); + assertThat(result.mentor().mentorId()).isEqualTo(mentor1.getId()); + assertThat(result.mentoring().mentoringId()).isEqualTo(mentoring1.getId()); + assertThat(result.mentoring().title()).isEqualTo(mentoring1.getTitle()); + assertThat(result.mentorSlot().startDateTime()).isEqualTo(request.startDateTime()); + assertThat(result.mentorSlot().endDateTime()).isEqualTo(request.endDateTime()); + assertThat(result.mentorSlot().mentorSlotStatus()).isEqualTo(MentorSlotStatus.AVAILABLE); verify(mentoringStorage).findMentoringByMentor(mentor1); verify(mentorSlotRepository).existsOverlappingSlot(mentor1.getId(), request.startDateTime(), request.endDateTime()); @@ -345,13 +345,13 @@ void updateMentorSlot() { // then assertThat(result).isNotNull(); - assertThat(result.mentorSlotId()).isEqualTo(slotId); - assertThat(result.mentorId()).isEqualTo(mentor1.getId()); - assertThat(result.mentoringId()).isEqualTo(mentoring1.getId()); - assertThat(result.mentoringTitle()).isEqualTo(mentoring1.getTitle()); - assertThat(result.startDateTime()).isEqualTo(request.startDateTime()); - assertThat(result.endDateTime()).isEqualTo(request.endDateTime()); - assertThat(result.mentorSlotStatus()).isEqualTo(MentorSlotStatus.AVAILABLE); + assertThat(result.mentorSlot().mentorSlotId()).isEqualTo(slotId); + assertThat(result.mentor().mentorId()).isEqualTo(mentor1.getId()); + assertThat(result.mentoring().mentoringId()).isEqualTo(mentoring1.getId()); + assertThat(result.mentoring().title()).isEqualTo(mentoring1.getTitle()); + assertThat(result.mentorSlot().startDateTime()).isEqualTo(request.startDateTime()); + assertThat(result.mentorSlot().endDateTime()).isEqualTo(request.endDateTime()); + assertThat(result.mentorSlot().mentorSlotStatus()).isEqualTo(MentorSlotStatus.AVAILABLE); verify(mentoringStorage).findMentorSlot(slotId); verify(mentorSlotRepository).existsOverlappingExcept( diff --git a/back/src/test/java/com/back/fixture/mentoring/MentoringTestFixture.java b/back/src/test/java/com/back/fixture/mentoring/MentoringTestFixture.java index 56efe895..f4f22fcc 100644 --- a/back/src/test/java/com/back/fixture/mentoring/MentoringTestFixture.java +++ b/back/src/test/java/com/back/fixture/mentoring/MentoringTestFixture.java @@ -45,11 +45,17 @@ public Mentoring createMentoring(Mentor mentor) { ); } - // TODO: saveAll로 변경 필요 public List createMentorings(Mentor mentor, int count) { - return IntStream.range(0, count) - .mapToObj(i -> createMentoring(mentor)) + List mentorings = IntStream.range(0, count) + .mapToObj(i -> Mentoring.builder() + .mentor(mentor) + .title("테스트 멘토링 " + (++counter)) + .bio("테스트 설명") + .tags(List.of("Spring", "Java")) + .build()) .toList(); + + return mentoringRepository.saveAll(mentorings); } @@ -66,7 +72,7 @@ public MentorSlot createMentorSlot(Mentor mentor, LocalDateTime startDateTime, L public MentorSlot createMentorSlot(Mentor mentor) { LocalDateTime baseDateTime = LocalDateTime.of(2025, 9, 30, 10, 0); - return createMentorSlot(mentor,baseDateTime, baseDateTime.minusHours(1)); + return createMentorSlot(mentor,baseDateTime, baseDateTime.plusHours(1)); } public List createMentorSlots(Mentor mentor, LocalDateTime baseDateTime, int days, int slots) {