diff --git a/.gitignore b/.gitignore index 3aefae5..4401768 100644 --- a/.gitignore +++ b/.gitignore @@ -42,4 +42,5 @@ application-pub.yml application-local.yml application-*.yml application_log -*.gz \ No newline at end of file +*.gz +!**/src/test/resources/application-test.yml \ No newline at end of file diff --git a/src/main/java/com/example/demo/controller/StudyOnceController.java b/src/main/java/com/example/demo/controller/StudyOnceController.java index 01d8570..d42aa9c 100644 --- a/src/main/java/com/example/demo/controller/StudyOnceController.java +++ b/src/main/java/com/example/demo/controller/StudyOnceController.java @@ -1,6 +1,7 @@ package com.example.demo.controller; import static com.example.demo.exception.ExceptionType.*; +import static com.example.demo.util.TruncatedTimeUtil.*; import java.time.LocalDateTime; @@ -96,7 +97,7 @@ public ResponseEntity update(@PathVariable Long studyOnceId, if (studyOnceService.doesOnlyStudyLeaderExist(studyOnceId)) { studyOnceService.updateStudyOnce(leaderId, studyOnceId, request, LocalDateTime.now()); } else { - studyOnceService.updateStudyOncePartially(leaderId, studyOnceId, request, LocalDateTime.now()); + studyOnceService.updateStudyOncePartially(leaderId, studyOnceId, request); } StudyOnceResponse response = studyOnceService.findStudyOnce(studyOnceId, LocalDateTime.now()); return ResponseEntity.ok(response); @@ -106,9 +107,8 @@ public ResponseEntity update(@PathVariable Long studyOnceId, public ResponseEntity tryJoin(@PathVariable Long studyOnceId, @RequestHeader("Authorization") String authorization) { long memberId = cafegoryTokenManager.getIdentityId(authorization); - LocalDateTime requestTime = LocalDateTime.now(); studyOnceService.tryJoin(memberId, studyOnceId); - return ResponseEntity.ok(new StudyOnceJoinResult(requestTime, true)); + return ResponseEntity.ok(new StudyOnceJoinResult(LOCAL_DATE_TIME_NOW, true)); } @DeleteMapping("/{studyOnceId:[0-9]+}") @@ -117,7 +117,8 @@ public ResponseEntity tryQuit(@PathVariable Long studyOnc long memberId = cafegoryTokenManager.getIdentityId(authorization); LocalDateTime requestTime = LocalDateTime.now(); studyOnceService.tryQuit(memberId, studyOnceId); - return ResponseEntity.ok(new StudyOnceQuitResponse(requestTime, true)); + return ResponseEntity.ok( + new StudyOnceQuitResponse(truncateDateTimeToSecond(requestTime), true)); } @PatchMapping("/{studyOnceId:[0-9]+}/attendance") @@ -126,7 +127,7 @@ public ResponseEntity takeAttendance(@PathVariable Lon @RequestBody UpdateAttendanceRequest request) { long leaderId = cafegoryTokenManager.getIdentityId(authorization); UpdateAttendanceResponse response = studyOnceService.updateAttendances(leaderId, studyOnceId, - request, LocalDateTime.now()); + request, LOCAL_DATE_TIME_NOW); return ResponseEntity.ok(response); } diff --git a/src/main/java/com/example/demo/domain/BaseEntity.java b/src/main/java/com/example/demo/domain/BaseEntity.java index 9f9be85..567ac5c 100644 --- a/src/main/java/com/example/demo/domain/BaseEntity.java +++ b/src/main/java/com/example/demo/domain/BaseEntity.java @@ -1,5 +1,7 @@ package com.example.demo.domain; +import static com.example.demo.util.TruncatedTimeUtil.*; + import java.time.LocalDateTime; import javax.persistence.Column; @@ -21,13 +23,13 @@ public class BaseEntity { @PrePersist public void prePersist() { - LocalDateTime now = LocalDateTime.now(); + LocalDateTime now = LOCAL_DATE_TIME_NOW; createdDate = now; lastModifiedDate = now; } @PreUpdate public void preUpdate() { - lastModifiedDate = LocalDateTime.now(); + lastModifiedDate = LOCAL_DATE_TIME_NOW; } } diff --git a/src/main/java/com/example/demo/domain/cafe/Address.java b/src/main/java/com/example/demo/domain/cafe/Address.java index 0f2f2c9..65aa78c 100644 --- a/src/main/java/com/example/demo/domain/cafe/Address.java +++ b/src/main/java/com/example/demo/domain/cafe/Address.java @@ -19,10 +19,6 @@ public Address(final String fullAddress, final String region) { this.region = region; } - public boolean isInRegion(String region) { - return true; - } - public String showFullAddress() { return getFullAddress(); } diff --git a/src/main/java/com/example/demo/domain/cafe/BusinessHour.java b/src/main/java/com/example/demo/domain/cafe/BusinessHour.java index 6ce0770..2af66d7 100644 --- a/src/main/java/com/example/demo/domain/cafe/BusinessHour.java +++ b/src/main/java/com/example/demo/domain/cafe/BusinessHour.java @@ -37,7 +37,10 @@ public class BusinessHour { @Column(name = "days_of_week") private String day; + /// columnDefinition 옵션은 나중에 DB에 직접 적용하고 삭제할 것 + @Column(columnDefinition = "TIME(6)") private LocalTime startTime; + @Column(columnDefinition = "TIME(6)") private LocalTime endTime; @ManyToOne(fetch = FetchType.LAZY) diff --git a/src/main/java/com/example/demo/domain/cafe/BusinessHourOpenChecker.java b/src/main/java/com/example/demo/domain/cafe/BusinessHourOpenChecker.java index 5b04a6f..308e2be 100644 --- a/src/main/java/com/example/demo/domain/cafe/BusinessHourOpenChecker.java +++ b/src/main/java/com/example/demo/domain/cafe/BusinessHourOpenChecker.java @@ -1,5 +1,7 @@ package com.example.demo.domain.cafe; +import static com.example.demo.util.TruncatedTimeUtil.*; + import java.time.DayOfWeek; import java.time.LocalDate; import java.time.LocalDateTime; @@ -40,7 +42,7 @@ private boolean isTodayBusinessDay(DayOfWeek businessDay, LocalDateTime now, boo } private boolean is24HourBusiness(LocalTime startTime, LocalTime endTime) { - return startTime.equals(LocalTime.MIN) && endTime.equals(LocalTime.MAX); + return startTime.equals(LocalTime.MIN) && endTime.equals(MAX_LOCAL_TIME); } private boolean isOpenOvernight(LocalTime startTime, LocalTime endTime) { @@ -58,7 +60,7 @@ private boolean isOpenDuringDay(LocalTime startTime, LocalTime endTime, LocalTim @Override public boolean checkWithBusinessHours(List businessHours, LocalDateTime now) { - if (!hasMatchingDayOfWeek(businessHours, now)) { + if (!hasMatchingDayOfWeek(businessHours, truncateDateTimeToSecond(now))) { throw new CafegoryException(ExceptionType.CAFE_NOT_FOUND_DAY_OF_WEEK); } return businessHours.stream() @@ -68,23 +70,27 @@ public boolean checkWithBusinessHours(List businessHours, LocalDat public boolean checkBetweenBusinessHours(LocalTime businessStartTime, LocalTime businessEndTime, LocalTime chosenStartTime, LocalTime chosenEndTime) { + LocalTime truncatedStartTime = truncateTimeToSecond(chosenStartTime); + LocalTime truncatedEndTime = truncateTimeToSecond(chosenEndTime); + // 영업 시작시간이 당일, 영업 종료시간이 당일 if (businessStartTime.isBefore(businessEndTime)) { - return (businessStartTime.equals(chosenStartTime) || businessStartTime.isBefore(chosenStartTime)) && ( - businessEndTime.equals(chosenEndTime) || businessEndTime.isAfter(chosenEndTime)); + return (businessStartTime.equals(truncatedStartTime) || businessStartTime.isBefore(truncatedStartTime)) + && ( + businessEndTime.equals(truncatedEndTime) || businessEndTime.isAfter(truncatedEndTime)); } // 영업 시작시간이 당일, 영업 종료시간이 다음날 if (businessStartTime.isAfter(businessEndTime)) { LocalDateTime businessStartDateTime = LocalDateTime.of(LocalDate.now(), businessStartTime); LocalDateTime businessEndDateTime = LocalDateTime.of(LocalDate.now().plusDays(1), businessEndTime); // 선택된 시작시간이 당일, 선택된 종료시간이 당일 || 선택된 시작시간이 다음날, 선택된 종료시간이 다음날 - if (chosenStartTime.isBefore(chosenEndTime)) { + if (truncatedStartTime.isBefore(truncatedEndTime)) { LocalDate chosenDate = LocalDate.now(); - boolean isChosenTimeOvernight = businessStartTime.isAfter(chosenStartTime); + boolean isChosenTimeOvernight = businessStartTime.isAfter(truncatedStartTime); LocalDate date = isChosenTimeOvernight ? chosenDate.plusDays(1) : chosenDate; LocalDateTime chosenStartDateTime = LocalDateTime.of(date, chosenStartTime); - LocalDateTime chosenEndDateTime = LocalDateTime.of(date, chosenEndTime); + LocalDateTime chosenEndDateTime = LocalDateTime.of(date, truncatedEndTime); return (businessStartDateTime.isBefore(chosenStartDateTime) || businessStartDateTime.equals( chosenStartDateTime)) @@ -92,9 +98,9 @@ public boolean checkBetweenBusinessHours(LocalTime businessStartTime, LocalTime chosenEndDateTime)); } // 선택된 시작시간이 당일, 선택된 종료시간이 다음날 - if (chosenStartTime.isAfter(chosenEndTime)) { - LocalDateTime chosenStartDateTime = LocalDateTime.of(LocalDate.now(), chosenStartTime); - LocalDateTime chosenEndDateTime = LocalDateTime.of(LocalDate.now().plusDays(1), chosenEndTime); + if (truncatedStartTime.isAfter(truncatedEndTime)) { + LocalDateTime chosenStartDateTime = LocalDateTime.of(LocalDate.now(), truncatedStartTime); + LocalDateTime chosenEndDateTime = LocalDateTime.of(LocalDate.now().plusDays(1), truncatedEndTime); return (businessStartDateTime.equals(chosenStartDateTime) || businessStartDateTime.isBefore( chosenStartDateTime)) && (businessEndDateTime.equals(chosenEndDateTime) || businessEndDateTime.isAfter(chosenEndDateTime)); diff --git a/src/main/java/com/example/demo/domain/cafe/Cafe.java b/src/main/java/com/example/demo/domain/cafe/Cafe.java index 45d63ff..77b10cf 100644 --- a/src/main/java/com/example/demo/domain/cafe/Cafe.java +++ b/src/main/java/com/example/demo/domain/cafe/Cafe.java @@ -1,13 +1,14 @@ package com.example.demo.domain.cafe; import static com.example.demo.exception.ExceptionType.*; +import static com.example.demo.util.TruncatedTimeUtil.*; import java.time.DayOfWeek; -import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; import java.util.OptionalDouble; +import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Embedded; import javax.persistence.Entity; @@ -54,7 +55,7 @@ public class Cafe { private boolean isAbleToStudy; private int minBeveragePrice; - @OneToMany(mappedBy = "cafe") + @OneToMany(mappedBy = "cafe", cascade = CascadeType.ALL, orphanRemoval = true) @Builder.Default private List businessHours = new ArrayList<>(); @@ -83,7 +84,7 @@ public String getRegion() { } public boolean isOpen(OpenChecker openChecker) { - return openChecker.checkWithBusinessHours(this.businessHours, LocalDateTime.now()); + return openChecker.checkWithBusinessHours(this.businessHours, LOCAL_DATE_TIME_NOW); } public OptionalDouble calcAverageRating() { @@ -98,4 +99,8 @@ public BusinessHour findBusinessHour(DayOfWeek dayOfWeek) { .findFirst() .orElseThrow(() -> new CafegoryException(CAFE_NOT_FOUND_DAY_OF_WEEK)); } + + public void changeBusinessHours(List businessHours) { + this.businessHours = businessHours; + } } diff --git a/src/main/java/com/example/demo/domain/cafe/CafeSearchCondition.java b/src/main/java/com/example/demo/domain/cafe/CafeSearchCondition.java index 2f77555..e175ef8 100644 --- a/src/main/java/com/example/demo/domain/cafe/CafeSearchCondition.java +++ b/src/main/java/com/example/demo/domain/cafe/CafeSearchCondition.java @@ -1,6 +1,7 @@ package com.example.demo.domain.cafe; import static com.example.demo.exception.ExceptionType.*; +import static com.example.demo.util.TruncatedTimeUtil.*; import java.time.LocalDateTime; import java.time.LocalTime; @@ -40,7 +41,7 @@ public static class Builder { private MinMenuPrice minMenuPrice; private LocalTime startTime; private LocalTime endTime; - private LocalDateTime now = LocalDateTime.now(); + private LocalDateTime now = LOCAL_DATE_TIME_NOW; public Builder(boolean isAbleToStudy, String region) { this.isAbleToStudy = isAbleToStudy; @@ -80,7 +81,7 @@ public CafeSearchCondition build() { private LocalTime calcLocalTime(int time) { if (time == END_TIME) { - return LocalTime.MAX; + return MAX_LOCAL_TIME; } return LocalTime.of(time, 0); } diff --git a/src/main/java/com/example/demo/domain/member/Member.java b/src/main/java/com/example/demo/domain/member/Member.java index 9816fd1..b49f048 100644 --- a/src/main/java/com/example/demo/domain/member/Member.java +++ b/src/main/java/com/example/demo/domain/member/Member.java @@ -6,7 +6,6 @@ import java.util.ArrayList; import java.util.List; -import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.ConstraintMode; import javax.persistence.Entity; @@ -45,7 +44,7 @@ public class Member { private String email; private String introduction; - @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST) + @OneToOne(fetch = FetchType.LAZY) @JoinColumn(name = "thumbnail_image_id", foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT)) private ThumbnailImage thumbnailImage; diff --git a/src/main/java/com/example/demo/domain/study/StudyOnce.java b/src/main/java/com/example/demo/domain/study/StudyOnce.java index 28a2a30..284169a 100644 --- a/src/main/java/com/example/demo/domain/study/StudyOnce.java +++ b/src/main/java/com/example/demo/domain/study/StudyOnce.java @@ -1,6 +1,7 @@ package com.example.demo.domain.study; import static com.example.demo.exception.ExceptionType.*; +import static com.example.demo.util.TruncatedTimeUtil.*; import java.time.Duration; import java.time.LocalDateTime; @@ -96,7 +97,7 @@ private StudyOnce(Long id, String name, Cafe cafe, LocalDateTime startDateTime, } private void validateStartDateTime(LocalDateTime startDateTime) { - LocalDateTime now = LocalDateTime.now(); + LocalDateTime now = LOCAL_DATE_TIME_NOW; Duration between = Duration.between(now, startDateTime); if (between.toSeconds() < 3 * 60 * 60) { throw new CafegoryException(ExceptionType.STUDY_ONCE_WRONG_START_TIME); @@ -116,7 +117,9 @@ private void validateStudyOnceTime(LocalDateTime startDateTime, LocalDateTime en } private void validateStartAndEndTime(LocalTime startLocalTime, LocalTime endLocalTime) { - if (!(startLocalTime.equals(LocalTime.of(23, 0)) && endLocalTime.equals(LocalTime.MAX))) { + if (!(startLocalTime.equals(LocalTime.of(23, 0)) && + (endLocalTime.equals(MAX_LOCAL_TIME) || endLocalTime.equals(LocalTime.of(23, 59, 59)))) + ) { throw new CafegoryException(STUDY_ONCE_SHORT_DURATION); } } @@ -199,7 +202,7 @@ public boolean isLeader(Member member) { } public boolean canJoin(LocalDateTime baseDateTime) { - Duration between = Duration.between(baseDateTime, startDateTime); + Duration between = Duration.between(truncateDateTimeToSecond(baseDateTime), startDateTime); return between.toSeconds() >= 60 * 60; } diff --git a/src/main/java/com/example/demo/mapper/CafeMapper.java b/src/main/java/com/example/demo/mapper/CafeMapper.java index 45c9c61..e8ab7bc 100644 --- a/src/main/java/com/example/demo/mapper/CafeMapper.java +++ b/src/main/java/com/example/demo/mapper/CafeMapper.java @@ -14,7 +14,6 @@ import com.example.demo.dto.cafe.CafeSearchListRequest; import com.example.demo.dto.cafe.CafeSearchListResponse; import com.example.demo.dto.cafe.CafeSearchResponse; -import com.example.demo.dto.cafe.CafeSearchReviewResponse; import com.example.demo.dto.cafe.CafeSearchSnsResponse; import com.example.demo.dto.cafe.CafeSearchStudyOnceResponse; import com.example.demo.dto.cafe.SnsResponse; @@ -90,7 +89,6 @@ public CafeSearchResponse toCafeSearchResponse( Cafe findCafe, List cafeSearchBusinessHourResponses, List cafeSearchSnsResponses, - List cafeSearchReviewResponses, List cafeSearchStudyOnceResponses, OpenChecker openChecker) { return CafeSearchResponse.builder() @@ -117,7 +115,6 @@ public CafeSearchResponse toCafeSearchResponseWithEmptyInfo( Cafe findCafe, List businessHourResponses, List snsResponses, - List reviewResponses, OpenChecker openChecker ) { return CafeSearchResponse.builder() diff --git a/src/main/java/com/example/demo/repository/study/StudyOnceRepositoryImpl.java b/src/main/java/com/example/demo/repository/study/StudyOnceRepositoryImpl.java index 9e5ff64..09118ec 100644 --- a/src/main/java/com/example/demo/repository/study/StudyOnceRepositoryImpl.java +++ b/src/main/java/com/example/demo/repository/study/StudyOnceRepositoryImpl.java @@ -1,5 +1,7 @@ package com.example.demo.repository.study; +import static com.example.demo.util.TruncatedTimeUtil.*; + import java.time.LocalDateTime; import java.util.List; @@ -54,7 +56,7 @@ public Long count(StudyOnceSearchRequest studyOnceSearchRequest) { } private BooleanExpression studyJoinAbleFilter(boolean onlyJoinAble) { - LocalDateTime base = LocalDateTime.now().plusHours(3); + LocalDateTime base = LOCAL_DATE_TIME_NOW.plusHours(3); if (onlyJoinAble) { return qStudyOnce.startDateTime.after(base) .or(qStudyOnce.startDateTime.eq(base)); diff --git a/src/main/java/com/example/demo/service/cafe/CafeServiceImpl.java b/src/main/java/com/example/demo/service/cafe/CafeServiceImpl.java index 57fc485..b0067be 100644 --- a/src/main/java/com/example/demo/service/cafe/CafeServiceImpl.java +++ b/src/main/java/com/example/demo/service/cafe/CafeServiceImpl.java @@ -77,7 +77,6 @@ public CafeSearchResponse searchCafeForMemberByCafeId(Long cafeId, Long memberId findCafe, businessHourMapper.toCafeSearchBusinessHourResponses(findCafe.getBusinessHours()), snsDetailMapper.toCafeSearchSnsResponses(findCafe.getSnsDetails()), - reviewMapper.toCafeSearchReviewResponses(findCafe.getReviews()), studyOnceMapper.toCafeSearchStudyOnceResponse(findCafe), openChecker ); @@ -90,7 +89,6 @@ public CafeSearchResponse searchCafeForNotMemberByCafeId(Long cafeId) { findCafe, businessHourMapper.toCafeSearchBusinessHourResponses(findCafe.getBusinessHours()), snsDetailMapper.toCafeSearchSnsResponses(findCafe.getSnsDetails()), - reviewMapper.toCafeSearchReviewResponses(findCafe.getReviews()), openChecker ); } diff --git a/src/main/java/com/example/demo/service/profile/ProfileService.java b/src/main/java/com/example/demo/service/profile/ProfileService.java index cd1d095..fc7cc9f 100644 --- a/src/main/java/com/example/demo/service/profile/ProfileService.java +++ b/src/main/java/com/example/demo/service/profile/ProfileService.java @@ -1,14 +1,20 @@ package com.example.demo.service.profile; +import static com.example.demo.util.TruncatedTimeUtil.*; + import java.time.LocalDateTime; +import org.springframework.transaction.annotation.Transactional; + import com.example.demo.dto.profile.ProfileGetResponse; import com.example.demo.dto.profile.ProfileUpdateRequest; import com.example.demo.dto.profile.ProfileUpdateResponse; public interface ProfileService { + + @Transactional default ProfileGetResponse get(Long requestMemberId, Long targetMemberId) { - return get(requestMemberId, targetMemberId, LocalDateTime.now()); + return get(requestMemberId, targetMemberId, LOCAL_DATE_TIME_NOW); } ProfileGetResponse get(Long requestMemberId, Long targetMemberId, LocalDateTime baseDateTime); diff --git a/src/main/java/com/example/demo/service/study/StudyOnceService.java b/src/main/java/com/example/demo/service/study/StudyOnceService.java index c530d9b..ccbb273 100644 --- a/src/main/java/com/example/demo/service/study/StudyOnceService.java +++ b/src/main/java/com/example/demo/service/study/StudyOnceService.java @@ -45,6 +45,5 @@ UpdateAttendanceResponse updateAttendances(long leaderId, long studyOnceId, void updateStudyOnce(long requestedMemberId, long studyOnceId, StudyOnceUpdateRequest request, LocalDateTime now); - void updateStudyOncePartially(long requestedMemberId, long studyOnceId, StudyOnceUpdateRequest request, - LocalDateTime now); + void updateStudyOncePartially(long requestedMemberId, long studyOnceId, StudyOnceUpdateRequest request); } diff --git a/src/main/java/com/example/demo/service/study/StudyOnceServiceImpl.java b/src/main/java/com/example/demo/service/study/StudyOnceServiceImpl.java index f266bb5..a845a34 100644 --- a/src/main/java/com/example/demo/service/study/StudyOnceServiceImpl.java +++ b/src/main/java/com/example/demo/service/study/StudyOnceServiceImpl.java @@ -1,6 +1,7 @@ package com.example.demo.service.study; import static com.example.demo.exception.ExceptionType.*; +import static com.example.demo.util.TruncatedTimeUtil.*; import java.time.Duration; import java.time.LocalDateTime; @@ -158,17 +159,19 @@ private void processAttendanceUpdates(long leaderId, long studyOnceId, UpdateAtt @Override public void updateAttendance(long leaderId, long studyOnceId, long memberId, Attendance attendance, LocalDateTime now) { + LocalDateTime microNow = truncateDateTimeToSecond(now); StudyOnce searched = findStudyOnceById(studyOnceId); + if (!studyOnceRepository.existsByLeaderId(leaderId)) { throw new CafegoryException(STUDY_ONCE_INVALID_LEADER); } - validateEarlyToTakeAttendance(now, searched.getStartDateTime()); - validateLateToTakeAttendance(now, searched.getStartDateTime(), searched.getEndDateTime()); + validateEarlyToTakeAttendance(microNow, searched.getStartDateTime()); + validateLateToTakeAttendance(microNow, searched.getStartDateTime(), searched.getEndDateTime()); StudyMember findStudyMember = studyMemberRepository.findById(new StudyMemberId(memberId, studyOnceId)) .orElseThrow(() -> new CafegoryException(STUDY_MEMBER_NOT_FOUND)); findStudyMember.setAttendance(attendance); - findStudyMember.setLastModifiedDate(now); + findStudyMember.setLastModifiedDate(microNow); } private void validateLateToTakeAttendance(LocalDateTime now, LocalDateTime startDateTime, @@ -196,10 +199,15 @@ private StudyOnce findStudyOnceById(long studyOnceId) { public StudyOnceCreateResponse createStudy(long leaderId, StudyOnceCreateRequest request) { Cafe cafe = findCafeById(request.getCafeId()); BusinessHour businessHour = cafe.findBusinessHour(request.getStartDateTime().getDayOfWeek()); - validateBetweenBusinessHour(request.getStartDateTime().toLocalTime(), request.getEndDateTime().toLocalTime(), + validateBetweenBusinessHour( + request.getStartDateTime().toLocalTime(), + request.getEndDateTime().toLocalTime(), businessHour); Member leader = findMemberById(leaderId); - validateStudyScheduleConflict(request.getStartDateTime(), request.getEndDateTime(), leader); + validateStudyScheduleConflict( + truncateDateTimeToSecond(request.getStartDateTime()), + truncateDateTimeToSecond(request.getEndDateTime()), + leader); StudyOnce studyOnce = studyOnceMapper.toNewEntity(request, cafe, leader); StudyOnce saved = studyOnceRepository.save(studyOnce); return studyOnceMapper.toStudyOnceCreateResponse(saved, true); @@ -237,7 +245,8 @@ public void updateStudyOnce(long requestedMemberId, long studyOnceId, StudyOnceU if (request.getStartDateTime() != null && request.getEndDateTime() != null) { Cafe cafe = studyOnce.getCafe(); validateBetweenBusinessHour(request.getStartDateTime().toLocalTime(), - request.getEndDateTime().toLocalTime(), cafe.findBusinessHour(now.getDayOfWeek())); + request.getEndDateTime().toLocalTime(), + cafe.findBusinessHour(truncateDateTimeToSecond(now).getDayOfWeek())); studyOnce.changeStudyOnceTime(request.getStartDateTime(), request.getEndDateTime()); } if (request.getOpenChatUrl() != null) { @@ -248,8 +257,7 @@ public void updateStudyOnce(long requestedMemberId, long studyOnceId, StudyOnceU } @Override - public void updateStudyOncePartially(long requestedMemberId, long studyOnceId, StudyOnceUpdateRequest request, - LocalDateTime now) { + public void updateStudyOncePartially(long requestedMemberId, long studyOnceId, StudyOnceUpdateRequest request) { StudyOnce studyOnce = findStudyOnceById(studyOnceId); if (!isStudyOnceLeader(requestedMemberId, studyOnceId)) { throw new CafegoryException(STUDY_ONCE_LEADER_PERMISSION_DENIED); @@ -280,7 +288,8 @@ public StudyMemberListResponse findStudyMembersById(Long studyOnceId) { @Override public StudyOnceResponse findStudyOnce(Long studyOnceId, LocalDateTime now) { StudyOnce studyOnce = findStudyOnceById(studyOnceId); - return studyOnceMapper.toStudyOnceResponse(studyOnce, studyOnce.canJoin(now)); + return studyOnceMapper.toStudyOnceResponse(studyOnce, + studyOnce.canJoin(truncateDateTimeToSecond(now))); } @Override @@ -304,12 +313,4 @@ private Cafe findCafeById(Long cafeId) { return cafeRepository.findById(cafeId) .orElseThrow(() -> new CafegoryException(CAFE_NOT_FOUND)); } - - private Member getMember(long leaderId, LocalDateTime startDateTime) { - Member leader = memberRepository.findById(leaderId) - .orElseThrow(() -> new CafegoryException(MEMBER_NOT_FOUND)); - var studyMembers = studyMemberRepository.findByMemberAndStudyDate(leader, startDateTime.toLocalDate()); - // leader.setStudyMembers(studyMembers); - return leader; - } } diff --git a/src/main/java/com/example/demo/util/TruncatedTimeUtil.java b/src/main/java/com/example/demo/util/TruncatedTimeUtil.java new file mode 100644 index 0000000..b16ff81 --- /dev/null +++ b/src/main/java/com/example/demo/util/TruncatedTimeUtil.java @@ -0,0 +1,19 @@ +package com.example.demo.util; + +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.temporal.ChronoUnit; + +public class TruncatedTimeUtil { + + public static final LocalTime MAX_LOCAL_TIME = LocalTime.of(23, 59, 59); + public static final LocalDateTime LOCAL_DATE_TIME_NOW = LocalDateTime.now().truncatedTo(ChronoUnit.SECONDS); + + public static LocalTime truncateTimeToSecond(LocalTime time) { + return time == null ? null : time.truncatedTo(ChronoUnit.SECONDS); + } + + public static LocalDateTime truncateDateTimeToSecond(LocalDateTime dateTime) { + return dateTime == null ? null : dateTime.truncatedTo(ChronoUnit.SECONDS); + } +} diff --git a/src/test/java/com/example/demo/config/TestConfig.java b/src/test/java/com/example/demo/config/TestConfig.java index 5e617bd..867df1a 100644 --- a/src/test/java/com/example/demo/config/TestConfig.java +++ b/src/test/java/com/example/demo/config/TestConfig.java @@ -44,27 +44,27 @@ public CafeSaveHelper cafeSaveHelper() { @Bean public MemberSaveHelper memberSaveHelper() { - return new MemberSaveHelper(memberRepository); + return new MemberSaveHelper(memberRepository, thumbnailImageRepository); } @Bean public ReviewSaveHelper reviewSaveHelper() { - return new ReviewSaveHelper(reviewRepository); + return new ReviewSaveHelper(reviewRepository, cafeRepository, memberRepository); } @Bean public StudyMemberSaveHelper studyMemberSaveHelper() { - return new StudyMemberSaveHelper(studyMemberRepository); + return new StudyMemberSaveHelper(studyMemberRepository, memberRepository, studyOnceRepository); } @Bean public StudyOnceCommentSaveHelper studyOnceCommentSaveHelper() { - return new StudyOnceCommentSaveHelper(studyOnceCommentRepository); + return new StudyOnceCommentSaveHelper(studyOnceCommentRepository, memberRepository, studyOnceRepository); } @Bean public StudyOnceSaveHelper studyOnceSaveHelper() { - return new StudyOnceSaveHelper(studyOnceRepository); + return new StudyOnceSaveHelper(studyOnceRepository, memberRepository, cafeRepository); } @Bean diff --git a/src/test/java/com/example/demo/domain/cafe/BusinessHourOpenCheckerTest.java b/src/test/java/com/example/demo/domain/cafe/BusinessHourOpenCheckerTest.java index c8ee391..b8f5d15 100644 --- a/src/test/java/com/example/demo/domain/cafe/BusinessHourOpenCheckerTest.java +++ b/src/test/java/com/example/demo/domain/cafe/BusinessHourOpenCheckerTest.java @@ -1,6 +1,7 @@ package com.example.demo.domain.cafe; import static com.example.demo.factory.TestBusinessHourFactory.*; +import static com.example.demo.util.TruncatedTimeUtil.*; import static org.assertj.core.api.Assertions.*; import java.time.LocalDateTime; @@ -67,10 +68,14 @@ private static Stream provideLocalDateTime5() { @DisplayName("24시간 영업한다.") void open_24Hours(LocalDateTime now) { List businessHours = List.of( + // createBusinessHourWithDayAndTime("MONDAY", LocalTime.of(0, 0), + // LocalTime.MAX), + // createBusinessHourWithDayAndTime("TUESDAY", LocalTime.of(0, 0), + // LocalTime.MAX) createBusinessHourWithDayAndTime("MONDAY", LocalTime.of(0, 0), - LocalTime.MAX), + MAX_LOCAL_TIME), createBusinessHourWithDayAndTime("TUESDAY", LocalTime.of(0, 0), - LocalTime.MAX) + MAX_LOCAL_TIME) ); BusinessHourOpenChecker sut = new BusinessHourOpenChecker(); //when @@ -122,11 +127,11 @@ void business_hours_are_different_each_day(LocalDateTime now, createBusinessHourWithDayAndTime("MONDAY", LocalTime.of(9, 0), LocalTime.of(22, 0)), createBusinessHourWithDayAndTime("TUESDAY", - LocalTime.of(9, 0), LocalTime.MAX), + LocalTime.of(9, 0), MAX_LOCAL_TIME), createBusinessHourWithDayAndTime("FRIDAY", - LocalTime.of(9, 0), LocalTime.MAX), + LocalTime.of(9, 0), MAX_LOCAL_TIME), createBusinessHourWithDayAndTime("SATURDAY", - LocalTime.of(0, 0), LocalTime.MAX), + LocalTime.of(0, 0), MAX_LOCAL_TIME), createBusinessHourWithDayAndTime("SUNDAY", LocalTime.of(0, 0), LocalTime.of(22, 0)) ); @@ -151,15 +156,15 @@ private static Stream provideLocalDateTime4() { 3일 : 토 4일 : 일 */ - Arguments.of(LocalDateTime.of(2024, 1, 29, 21, 59, 59, 999_999_999), true), + Arguments.of(LocalDateTime.of(2024, 1, 29, 21, 59, 59, 999_999_000), true), Arguments.of(LocalDateTime.of(2024, 1, 29, 22, 0), false), - Arguments.of(LocalDateTime.of(2024, 1, 30, 23, 59, 59, 999_999_998), true), - Arguments.of(LocalDateTime.of(2024, 1, 30, 23, 59, 59, 999_999_999), false), - Arguments.of(LocalDateTime.of(2024, 2, 2, 23, 59, 59, 999_999_998), true), - Arguments.of(LocalDateTime.of(2024, 2, 2, 23, 59, 59, 999_999_999), false), + Arguments.of(LocalDateTime.of(2024, 1, 30, 23, 59, 58), true), + Arguments.of(LocalDateTime.of(2024, 1, 30, 23, 59, 59, 999_999_000), false), + Arguments.of(LocalDateTime.of(2024, 2, 2, 23, 59, 58), true), + Arguments.of(LocalDateTime.of(2024, 2, 2, 23, 59, 59, 999_999_000), false), Arguments.of(LocalDateTime.of(2024, 2, 3, 0, 0), true), Arguments.of(LocalDateTime.of(2024, 2, 4, 0, 0), true), - Arguments.of(LocalDateTime.of(2024, 2, 4, 21, 59, 59, 999_999_999), true), + Arguments.of(LocalDateTime.of(2024, 2, 4, 21, 59, 59, 999_999_000), true), Arguments.of(LocalDateTime.of(2024, 2, 4, 22, 0, 0), false) ); } @@ -188,7 +193,7 @@ private static Stream provideChosenTimeAndExpected() { true ), Arguments.of( - LocalTime.of(9, 0, 0, 1), + LocalTime.of(9, 0, 0, 100_000_000), LocalTime.of(21, 0), true ), @@ -198,7 +203,7 @@ private static Stream provideChosenTimeAndExpected() { true ), Arguments.of( - LocalTime.of(9, 0, 0, 1), + LocalTime.of(9, 0, 0, 100_000_000), LocalTime.of(20, 59, 59, 999_999_999), true ), @@ -209,12 +214,12 @@ private static Stream provideChosenTimeAndExpected() { ), Arguments.of( LocalTime.of(9, 0, 0), - LocalTime.of(21, 0, 0, 1), + LocalTime.of(21, 0, 1), false ), Arguments.of( LocalTime.of(8, 59, 59, 999_999_999), - LocalTime.of(21, 0, 0, 1), + LocalTime.of(21, 0, 0, 100_000_000), false ) ); @@ -225,9 +230,9 @@ private static Stream provideChosenTimeAndExpected() { void check_if_chosen_time_is_within_24hour_business_hours() { //given LocalTime businessStartTime = LocalTime.of(0, 0); - LocalTime businessEndTime = LocalTime.MAX; + LocalTime businessEndTime = MAX_LOCAL_TIME; LocalTime chosenStartTime = LocalTime.of(0, 0); - LocalTime chosenEndTime = LocalTime.MAX; + LocalTime chosenEndTime = MAX_LOCAL_TIME; BusinessHourOpenChecker sut = new BusinessHourOpenChecker(); //when boolean isBetween = sut.checkBetweenBusinessHours(businessStartTime, businessEndTime, @@ -267,7 +272,7 @@ private static Stream provideChosenTimeAndExpected4() { ), Arguments.of( LocalTime.of(23, 0), - LocalTime.MAX, + MAX_LOCAL_TIME, true ), Arguments.of( @@ -282,7 +287,7 @@ private static Stream provideChosenTimeAndExpected4() { ), Arguments.of( LocalTime.of(23, 0), - LocalTime.of(2, 0, 0, 1), + LocalTime.of(2, 0, 1), false ), Arguments.of( @@ -297,7 +302,7 @@ private static Stream provideChosenTimeAndExpected4() { ), Arguments.of( LocalTime.of(0, 0), - LocalTime.of(2, 0, 0, 1), + LocalTime.of(2, 0, 1), false ), Arguments.of( @@ -312,7 +317,7 @@ private static Stream provideChosenTimeAndExpected4() { ), Arguments.of( LocalTime.of(7, 0), - LocalTime.of(2, 0, 0, 1), + LocalTime.of(2, 0, 1), false ) ); diff --git a/src/test/java/com/example/demo/domain/study/StudyOnceTest.java b/src/test/java/com/example/demo/domain/study/StudyOnceTest.java index 696feec..591f767 100644 --- a/src/test/java/com/example/demo/domain/study/StudyOnceTest.java +++ b/src/test/java/com/example/demo/domain/study/StudyOnceTest.java @@ -46,7 +46,7 @@ private static Stream provideTimeAndExpected() { LocalDateTime start = NOW.plusHours(4); return Stream.of( Arguments.of(start.minusHours(1), start, true), - Arguments.of(start.minusHours(1).plusNanos(1), start, false) + Arguments.of(start.minusHours(1).plusSeconds(1), start, false) ); } @@ -74,7 +74,7 @@ void join_fails_when_less_than_1hour_before_start() { StudyOnce sut = createStudyOnceWithTime(cafe, leader, NOW.plusHours(4), NOW.plusHours(6)); //when assertThatThrownBy( - () -> sut.tryJoin(member, NOW.plusHours(3).plusNanos(1))) + () -> sut.tryJoin(member, NOW.plusHours(3).plusNanos(100_000_000))) .isInstanceOf(CafegoryException.class) .hasMessage(STUDY_ONCE_TOO_LATE_JOIN.getErrorMessage()); } @@ -162,7 +162,7 @@ void can_not_quit_study_after_confirmation() { sut.tryJoin(member, NOW); //then assertThatThrownBy( - () -> sut.tryQuit(member, NOW.plusHours(3).plusNanos(1))) + () -> sut.tryQuit(member, NOW.plusHours(3).plusNanos(100_000_000))) .isInstanceOf(CafegoryException.class) .hasMessage(STUDY_ONCE_TOO_LATE_QUIT.getErrorMessage()); } diff --git a/src/test/java/com/example/demo/factory/TestBusinessHourFactory.java b/src/test/java/com/example/demo/factory/TestBusinessHourFactory.java index 0fc3342..956ece3 100644 --- a/src/test/java/com/example/demo/factory/TestBusinessHourFactory.java +++ b/src/test/java/com/example/demo/factory/TestBusinessHourFactory.java @@ -1,5 +1,7 @@ package com.example.demo.factory; +import static com.example.demo.util.TruncatedTimeUtil.*; + import java.time.LocalTime; import com.example.demo.domain.cafe.BusinessHour; @@ -10,7 +12,26 @@ public class TestBusinessHourFactory { public static BusinessHour createBusinessHourWithDayAnd24For7(String day) { return BusinessHour.builder() .startTime(LocalTime.MIN) - .endTime(LocalTime.MAX) + .endTime(MAX_LOCAL_TIME) + .day(day) + .build(); + } + + public static BusinessHour createBusinessHourWithDayAnd24For7(Cafe cafe, String day) { + return BusinessHour.builder() + .cafe(cafe) + .startTime(LocalTime.MIN) + .endTime(MAX_LOCAL_TIME) + .day(day) + .build(); + } + + public static BusinessHour createBusinessHourWithDayAndTime(Cafe cafe, String day, LocalTime startTime, + LocalTime endTime) { + return BusinessHour.builder() + .cafe(cafe) + .startTime(startTime) + .endTime(endTime) .day(day) .build(); } diff --git a/src/test/java/com/example/demo/helper/CafeSaveHelper.java b/src/test/java/com/example/demo/helper/CafeSaveHelper.java index 3a033f6..5b1b6a8 100644 --- a/src/test/java/com/example/demo/helper/CafeSaveHelper.java +++ b/src/test/java/com/example/demo/helper/CafeSaveHelper.java @@ -1,8 +1,13 @@ package com.example.demo.helper; +import static com.example.demo.factory.TestBusinessHourFactory.*; + +import java.time.LocalTime; import java.util.ArrayList; import java.util.List; +import org.springframework.transaction.annotation.Transactional; + import com.example.demo.domain.cafe.BusinessHour; import com.example.demo.domain.cafe.Cafe; import com.example.demo.factory.TestBusinessHourFactory; @@ -12,6 +17,7 @@ import lombok.RequiredArgsConstructor; @RequiredArgsConstructor +@Transactional public class CafeSaveHelper { private final CafeRepository cafeRepository; @@ -21,24 +27,41 @@ public Cafe saveCafe() { return cafeRepository.save(cafe); } - public Cafe saveCafeWithBusinessHour(List businessHours) { - Cafe cafe = TestCafeFactory.createCafeWithBusinessHours(businessHours); + public Cafe saveCafeWith7daysFrom9To21() { + Cafe cafe = TestCafeFactory.createCafe(); + List businessHours = createBusinessHoursWith7daysFrom9To21(cafe); + cafe.changeBusinessHours(businessHours); return cafeRepository.save(cafe); } + private List createBusinessHoursWith7daysFrom9To21(Cafe cafe) { + List businessHours = new ArrayList<>(); + List daysOfWeek = generateDaysOfWeek(); + for (String day : daysOfWeek) { + businessHours.add( + createBusinessHourWithDayAndTime(cafe, day, LocalTime.of(9, 0), LocalTime.of(21, 0)) + ); + } + return businessHours; + } + public Cafe saveCafeWith24For7() { - List businessHours = makeBusinessHourWith24For7(); - Cafe cafe = TestCafeFactory.createCafeWithBusinessHours(businessHours); + Cafe cafe = TestCafeFactory.createCafe(); + List businessHours = makeBusinessHourWith24For7(cafe); + cafe.changeBusinessHours(businessHours); return cafeRepository.save(cafe); } - private List makeBusinessHourWith24For7() { - List daysOfWeek = List.of("MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY", "SATURDAY", "SUNDAY"); + private List generateDaysOfWeek() { + return List.of("MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY", "SATURDAY", "SUNDAY"); + } + + private List makeBusinessHourWith24For7(Cafe cafe) { + List daysOfWeek = generateDaysOfWeek(); List businessHours = new ArrayList<>(); for (String day : daysOfWeek) { - businessHours.add( - TestBusinessHourFactory.createBusinessHourWithDayAnd24For7(day) - ); + BusinessHour businessHour = TestBusinessHourFactory.createBusinessHourWithDayAnd24For7(cafe, day); + businessHours.add(businessHour); } return businessHours; } diff --git a/src/test/java/com/example/demo/helper/MemberSaveHelper.java b/src/test/java/com/example/demo/helper/MemberSaveHelper.java index bec9b3c..cb8d59d 100644 --- a/src/test/java/com/example/demo/helper/MemberSaveHelper.java +++ b/src/test/java/com/example/demo/helper/MemberSaveHelper.java @@ -1,24 +1,31 @@ package com.example.demo.helper; +import org.springframework.transaction.annotation.Transactional; + import com.example.demo.domain.member.Member; import com.example.demo.domain.member.ThumbnailImage; import com.example.demo.factory.TestMemberFactory; import com.example.demo.repository.member.MemberRepository; +import com.example.demo.repository.thumbnailimage.ThumbnailImageRepository; import lombok.RequiredArgsConstructor; @RequiredArgsConstructor +@Transactional public class MemberSaveHelper { private final MemberRepository memberRepository; + private final ThumbnailImageRepository thumbnailImageRepository; public Member saveMember(ThumbnailImage thumbnailImage) { - Member member = TestMemberFactory.createMemberWithThumbnailImage(thumbnailImage); + ThumbnailImage mergedThumbnailImage = thumbnailImageRepository.save(thumbnailImage); + Member member = TestMemberFactory.createMemberWithThumbnailImage(mergedThumbnailImage); return memberRepository.save(member); } public Member saveMemberWithName(ThumbnailImage thumbnailImage, String name) { - Member member = TestMemberFactory.createMemberWithThumbAndName(thumbnailImage, name); + ThumbnailImage mergedThumbnailImage = thumbnailImageRepository.save(thumbnailImage); + Member member = TestMemberFactory.createMemberWithThumbAndName(mergedThumbnailImage, name); return memberRepository.save(member); } } diff --git a/src/test/java/com/example/demo/helper/ReviewSaveHelper.java b/src/test/java/com/example/demo/helper/ReviewSaveHelper.java index 498e16e..c891cf1 100644 --- a/src/test/java/com/example/demo/helper/ReviewSaveHelper.java +++ b/src/test/java/com/example/demo/helper/ReviewSaveHelper.java @@ -1,20 +1,29 @@ package com.example.demo.helper; +import org.springframework.transaction.annotation.Transactional; + import com.example.demo.domain.cafe.Cafe; import com.example.demo.domain.member.Member; import com.example.demo.domain.review.Review; import com.example.demo.factory.TestReviewFactory; +import com.example.demo.repository.cafe.CafeRepository; +import com.example.demo.repository.member.MemberRepository; import com.example.demo.repository.review.ReviewRepository; import lombok.RequiredArgsConstructor; @RequiredArgsConstructor +@Transactional public class ReviewSaveHelper { private final ReviewRepository reviewRepository; + private final CafeRepository cafeRepository; + private final MemberRepository memberRepository; public Review saveReview(Cafe cafe, Member member) { - Review review = TestReviewFactory.createReview(cafe, member); + Cafe mergedCafe = cafeRepository.save(cafe); + Member mergedMember = memberRepository.save(member); + Review review = TestReviewFactory.createReview(mergedCafe, mergedMember); return reviewRepository.save(review); } } diff --git a/src/test/java/com/example/demo/helper/StudyMemberSaveHelper.java b/src/test/java/com/example/demo/helper/StudyMemberSaveHelper.java index 34b50cc..ef7d38c 100644 --- a/src/test/java/com/example/demo/helper/StudyMemberSaveHelper.java +++ b/src/test/java/com/example/demo/helper/StudyMemberSaveHelper.java @@ -1,20 +1,29 @@ package com.example.demo.helper; +import org.springframework.transaction.annotation.Transactional; + import com.example.demo.domain.member.Member; import com.example.demo.domain.study.StudyMember; import com.example.demo.domain.study.StudyOnce; import com.example.demo.factory.TestStudyMemberFactory; +import com.example.demo.repository.member.MemberRepository; import com.example.demo.repository.study.StudyMemberRepository; +import com.example.demo.repository.study.StudyOnceRepository; import lombok.RequiredArgsConstructor; @RequiredArgsConstructor +@Transactional public class StudyMemberSaveHelper { private final StudyMemberRepository studyMemberRepository; + private final MemberRepository memberRepository; + private final StudyOnceRepository studyOnceRepository; public StudyMember saveStudyMember(Member member, StudyOnce studyOnce) { - StudyMember studyMember = TestStudyMemberFactory.createStudyMember(member, studyOnce); + Member mergedMember = memberRepository.save(member); + StudyOnce mergedStudyOnce = studyOnceRepository.save(studyOnce); + StudyMember studyMember = TestStudyMemberFactory.createStudyMember(mergedMember, mergedStudyOnce); return studyMemberRepository.save(studyMember); } } diff --git a/src/test/java/com/example/demo/helper/StudyOnceCommentSaveHelper.java b/src/test/java/com/example/demo/helper/StudyOnceCommentSaveHelper.java index 43ddea1..5d2927d 100644 --- a/src/test/java/com/example/demo/helper/StudyOnceCommentSaveHelper.java +++ b/src/test/java/com/example/demo/helper/StudyOnceCommentSaveHelper.java @@ -1,33 +1,49 @@ package com.example.demo.helper; +import org.springframework.transaction.annotation.Transactional; + import com.example.demo.domain.member.Member; import com.example.demo.domain.study.StudyOnce; import com.example.demo.domain.study.StudyOnceComment; import com.example.demo.factory.TestStudyOnceCommentFactory; +import com.example.demo.repository.member.MemberRepository; import com.example.demo.repository.study.StudyOnceCommentRepository; +import com.example.demo.repository.study.StudyOnceRepository; import lombok.RequiredArgsConstructor; @RequiredArgsConstructor +@Transactional public class StudyOnceCommentSaveHelper { private final StudyOnceCommentRepository studyOnceCommentRepository; + private final MemberRepository memberRepository; + private final StudyOnceRepository studyOnceRepository; public StudyOnceComment saveStudyOnceQuestion(Member member, StudyOnce studyOnce) { - StudyOnceComment studyOnceComment = TestStudyOnceCommentFactory.createStudyOnceQuestion(member, studyOnce); + Member mergedMember = memberRepository.save(member); + StudyOnce mergedStudyOnce = studyOnceRepository.save(studyOnce); + StudyOnceComment studyOnceComment = TestStudyOnceCommentFactory.createStudyOnceQuestion(mergedMember, + mergedStudyOnce); return studyOnceCommentRepository.save(studyOnceComment); } public StudyOnceComment saveStudyOnceQuestionWithContent(Member member, StudyOnce studyOnce, String content) { - StudyOnceComment studyOnceComment = TestStudyOnceCommentFactory.createStudyOnceQuestionWithContent(member, - studyOnce, content); + Member mergedMember = memberRepository.save(member); + StudyOnce mergedStudyOnce = studyOnceRepository.save(studyOnce); + StudyOnceComment studyOnceComment = TestStudyOnceCommentFactory.createStudyOnceQuestionWithContent(mergedMember, + mergedStudyOnce, content); return studyOnceCommentRepository.save(studyOnceComment); } public StudyOnceComment saveStudyOnceReplyWithContent(Member member, StudyOnce studyOnce, StudyOnceComment parent, String content) { - StudyOnceComment reply = TestStudyOnceCommentFactory.createStudyOnceReplyWithContent(member, studyOnce, parent, + Member mergedMember = memberRepository.save(member); + StudyOnce mergedStudyOnce = studyOnceRepository.save(studyOnce); + StudyOnceComment mergedParent = studyOnceCommentRepository.save(parent); + StudyOnceComment reply = TestStudyOnceCommentFactory.createStudyOnceReplyWithContent(mergedMember, + mergedStudyOnce, mergedParent, content); parent.getChildren().add(reply); return studyOnceCommentRepository.save(reply); diff --git a/src/test/java/com/example/demo/helper/StudyOnceSaveHelper.java b/src/test/java/com/example/demo/helper/StudyOnceSaveHelper.java index a42a126..5b841ee 100644 --- a/src/test/java/com/example/demo/helper/StudyOnceSaveHelper.java +++ b/src/test/java/com/example/demo/helper/StudyOnceSaveHelper.java @@ -2,27 +2,39 @@ import java.time.LocalDateTime; +import org.springframework.transaction.annotation.Transactional; + import com.example.demo.domain.cafe.Cafe; import com.example.demo.domain.member.Member; import com.example.demo.domain.study.StudyOnce; import com.example.demo.factory.TestStudyOnceFactory; +import com.example.demo.repository.cafe.CafeRepository; +import com.example.demo.repository.member.MemberRepository; import com.example.demo.repository.study.StudyOnceRepository; import lombok.RequiredArgsConstructor; @RequiredArgsConstructor +@Transactional public class StudyOnceSaveHelper { private final StudyOnceRepository studyOnceRepository; + private final MemberRepository memberRepository; + private final CafeRepository cafeRepository; public StudyOnce saveStudyOnce(Cafe cafe, Member leader) { - StudyOnce studyOnce = TestStudyOnceFactory.createStudyOnce(cafe, leader); + Member mergedMember = memberRepository.save(leader); + Cafe mergedCafe = cafeRepository.save(cafe); + StudyOnce studyOnce = TestStudyOnceFactory.createStudyOnce(mergedCafe, mergedMember); return studyOnceRepository.save(studyOnce); } public StudyOnce saveStudyOnceWithTime(Cafe cafe, Member leader, LocalDateTime startDateTime, LocalDateTime endDateTime) { - StudyOnce studyOnce = TestStudyOnceFactory.createStudyOnceWithTime(cafe, leader, startDateTime, endDateTime); + Member mergedLeader = memberRepository.save(leader); + Cafe mergedCafe = cafeRepository.save(cafe); + StudyOnce studyOnce = TestStudyOnceFactory.createStudyOnceWithTime(mergedCafe, mergedLeader, startDateTime, + endDateTime); return studyOnceRepository.save(studyOnce); } } diff --git a/src/test/java/com/example/demo/helper/ThumbnailImageSaveHelper.java b/src/test/java/com/example/demo/helper/ThumbnailImageSaveHelper.java index 12a401d..26e0426 100644 --- a/src/test/java/com/example/demo/helper/ThumbnailImageSaveHelper.java +++ b/src/test/java/com/example/demo/helper/ThumbnailImageSaveHelper.java @@ -1,5 +1,7 @@ package com.example.demo.helper; +import org.springframework.transaction.annotation.Transactional; + import com.example.demo.domain.member.ThumbnailImage; import com.example.demo.factory.TestThumbnailImageFactory; import com.example.demo.repository.thumbnailimage.ThumbnailImageRepository; @@ -7,6 +9,7 @@ import lombok.RequiredArgsConstructor; @RequiredArgsConstructor +@Transactional public class ThumbnailImageSaveHelper { private final ThumbnailImageRepository thumbnailImageRepository; diff --git a/src/test/java/com/example/demo/repository/cafe/CafeRepositorySearchMethodTest.java b/src/test/java/com/example/demo/repository/cafe/CafeRepositorySearchMethodTest.java index 559c812..bae5b85 100644 --- a/src/test/java/com/example/demo/repository/cafe/CafeRepositorySearchMethodTest.java +++ b/src/test/java/com/example/demo/repository/cafe/CafeRepositorySearchMethodTest.java @@ -2,6 +2,7 @@ import static com.example.demo.factory.TestBusinessHourFactory.*; import static com.example.demo.factory.TestCafeFactory.*; +import static com.example.demo.util.TruncatedTimeUtil.*; import static org.assertj.core.api.Assertions.*; import java.sql.Time; @@ -351,8 +352,8 @@ private static Stream provideConditionByFilteringTimeAndExpected() { @Test @DisplayName("영업시간이 24시간인 경우, 영업시간으로 필터링") void search_cafes_with_24hours_businessHours_() { - setUp("상수동", MaxAllowableStay.TWO_HOUR, true, 2_500, LocalTime.of(0, 0), LocalTime.MAX); - setUp("상수동", MaxAllowableStay.TWO_HOUR, true, 2_500, LocalTime.of(0, 0), LocalTime.MAX); + setUp("상수동", MaxAllowableStay.TWO_HOUR, true, 2_500, LocalTime.of(0, 0), MAX_LOCAL_TIME); + setUp("상수동", MaxAllowableStay.TWO_HOUR, true, 2_500, LocalTime.of(0, 0), MAX_LOCAL_TIME); //given CafeSearchCondition cafeSearchCondition = createSearchConditionByFilteringTime(true, "상수동", 0, 24, diff --git a/src/test/java/com/example/demo/service/ServiceTest.java b/src/test/java/com/example/demo/service/ServiceTest.java new file mode 100644 index 0000000..9ac16e2 --- /dev/null +++ b/src/test/java/com/example/demo/service/ServiceTest.java @@ -0,0 +1,24 @@ +package com.example.demo.service; + +import org.junit.jupiter.api.BeforeEach; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.ActiveProfiles; + +import com.example.demo.config.TestConfig; +import com.example.demo.utils.DatabaseCleanup; + +@SpringBootTest +@ActiveProfiles("test") +@Import({TestConfig.class}) +public class ServiceTest { + + @Autowired + private DatabaseCleanup databaseCleanup; + + @BeforeEach + public void setUp() { + databaseCleanup.execute(); + } +} diff --git a/src/test/java/com/example/demo/service/profile/ProfileServiceImplTest.java b/src/test/java/com/example/demo/service/profile/ProfileServiceImplTest.java index 6669813..f34d518 100644 --- a/src/test/java/com/example/demo/service/profile/ProfileServiceImplTest.java +++ b/src/test/java/com/example/demo/service/profile/ProfileServiceImplTest.java @@ -5,15 +5,10 @@ import java.time.LocalDateTime; -import javax.transaction.Transactional; - import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.context.annotation.Import; -import com.example.demo.config.TestConfig; import com.example.demo.domain.cafe.Cafe; import com.example.demo.domain.member.Member; import com.example.demo.domain.member.ThumbnailImage; @@ -26,12 +21,10 @@ import com.example.demo.helper.MemberSaveHelper; import com.example.demo.helper.StudyOnceSaveHelper; import com.example.demo.helper.ThumbnailImageSaveHelper; +import com.example.demo.service.ServiceTest; import com.example.demo.service.study.StudyOnceService; -@SpringBootTest -@Import({TestConfig.class}) -@Transactional -class ProfileServiceImplTest { +class ProfileServiceImplTest extends ServiceTest { private static final LocalDateTime NOW = LocalDateTime.now(); diff --git a/src/test/java/com/example/demo/service/review/ReviewServiceTest.java b/src/test/java/com/example/demo/service/review/ReviewServiceTest.java index e918ed1..1edd2cb 100644 --- a/src/test/java/com/example/demo/service/review/ReviewServiceTest.java +++ b/src/test/java/com/example/demo/service/review/ReviewServiceTest.java @@ -5,16 +5,11 @@ import java.util.List; -import javax.transaction.Transactional; - import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.context.annotation.Import; -import com.example.demo.config.TestConfig; import com.example.demo.domain.cafe.Cafe; import com.example.demo.domain.member.Member; import com.example.demo.domain.member.ThumbnailImage; @@ -26,11 +21,9 @@ import com.example.demo.helper.ReviewSaveHelper; import com.example.demo.helper.ThumbnailImageSaveHelper; import com.example.demo.repository.review.ReviewRepository; +import com.example.demo.service.ServiceTest; -@SpringBootTest -@Import({TestConfig.class}) -@Transactional -class ReviewServiceTest { +class ReviewServiceTest extends ServiceTest { @Autowired private ReviewService sut; diff --git a/src/test/java/com/example/demo/service/study/StudyOnceCommentQueryServiceImplTest.java b/src/test/java/com/example/demo/service/study/StudyOnceCommentQueryServiceImplTest.java index b0d46d5..4501268 100644 --- a/src/test/java/com/example/demo/service/study/StudyOnceCommentQueryServiceImplTest.java +++ b/src/test/java/com/example/demo/service/study/StudyOnceCommentQueryServiceImplTest.java @@ -8,11 +8,7 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.context.annotation.Import; -import org.springframework.transaction.annotation.Transactional; -import com.example.demo.config.TestConfig; import com.example.demo.domain.cafe.Cafe; import com.example.demo.domain.member.Member; import com.example.demo.domain.member.ThumbnailImage; @@ -26,11 +22,9 @@ import com.example.demo.helper.StudyOnceCommentSaveHelper; import com.example.demo.helper.StudyOnceSaveHelper; import com.example.demo.helper.ThumbnailImageSaveHelper; +import com.example.demo.service.ServiceTest; -@SpringBootTest -@Import({TestConfig.class}) -@Transactional -class StudyOnceCommentQueryServiceImplTest { +class StudyOnceCommentQueryServiceImplTest extends ServiceTest { @Autowired private StudyOnceCommentQueryService sut; diff --git a/src/test/java/com/example/demo/service/study/StudyOnceCommentServiceImplTest.java b/src/test/java/com/example/demo/service/study/StudyOnceCommentServiceImplTest.java index f47f005..7add707 100644 --- a/src/test/java/com/example/demo/service/study/StudyOnceCommentServiceImplTest.java +++ b/src/test/java/com/example/demo/service/study/StudyOnceCommentServiceImplTest.java @@ -4,15 +4,10 @@ import java.util.List; -import javax.transaction.Transactional; - import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.context.annotation.Import; -import com.example.demo.config.TestConfig; import com.example.demo.domain.cafe.Cafe; import com.example.demo.domain.member.Member; import com.example.demo.domain.member.ThumbnailImage; @@ -28,11 +23,9 @@ import com.example.demo.helper.StudyOnceSaveHelper; import com.example.demo.helper.ThumbnailImageSaveHelper; import com.example.demo.repository.study.StudyOnceCommentRepository; +import com.example.demo.service.ServiceTest; -@SpringBootTest -@Import({TestConfig.class}) -@Transactional -class StudyOnceCommentServiceImplTest { +class StudyOnceCommentServiceImplTest extends ServiceTest { @Autowired private StudyOnceCommentService sut; diff --git a/src/test/java/com/example/demo/service/study/StudyOnceServiceImplTest.java b/src/test/java/com/example/demo/service/study/StudyOnceServiceImplTest.java index f763cd3..3c3a560 100644 --- a/src/test/java/com/example/demo/service/study/StudyOnceServiceImplTest.java +++ b/src/test/java/com/example/demo/service/study/StudyOnceServiceImplTest.java @@ -2,16 +2,11 @@ import static com.example.demo.domain.study.Attendance.*; import static com.example.demo.exception.ExceptionType.*; -import static com.example.demo.factory.TestBusinessHourFactory.*; import static org.assertj.core.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*; import java.time.LocalDateTime; -import java.time.LocalTime; -import java.util.ArrayList; -import java.util.Collection; import java.util.List; -import java.util.stream.Collectors; import java.util.stream.Stream; import org.junit.jupiter.api.DisplayName; @@ -21,12 +16,7 @@ import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.ValueSource; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.context.annotation.Import; -import org.springframework.transaction.annotation.Transactional; -import com.example.demo.config.TestConfig; -import com.example.demo.domain.cafe.BusinessHour; import com.example.demo.domain.cafe.Cafe; import com.example.demo.domain.member.Member; import com.example.demo.domain.member.ThumbnailImage; @@ -48,11 +38,9 @@ import com.example.demo.helper.ThumbnailImageSaveHelper; import com.example.demo.repository.study.StudyMemberRepository; import com.example.demo.repository.study.StudyOnceRepository; +import com.example.demo.service.ServiceTest; -@SpringBootTest -@Import({TestConfig.class}) -@Transactional -class StudyOnceServiceImplTest { +class StudyOnceServiceImplTest extends ServiceTest { private static final LocalDateTime NOW = LocalDateTime.now(); @Autowired @@ -81,14 +69,6 @@ private StudyOnceCreateRequest makeStudyOnceCreateRequest(LocalDateTime start, L return new StudyOnceCreateRequest(cafeId, "테스트 스터디", start, end, 4, true, "오픈채팅방 링크"); } - private void syncStudyOnceRepositoryAndStudyMemberRepository() { - List allStudyMembers = studyOnceRepository.findAll().stream() - .map(StudyOnce::getStudyMembers) - .flatMap(Collection::stream) - .collect(Collectors.toList()); - studyMemberRepository.saveAll(allStudyMembers); - } - @Test @DisplayName("회원이 아닐떄 카공을 조회하면 카공의 참석여부는 false를 반환한다.") void searchByStudyId_when_not_member() { @@ -120,7 +100,6 @@ void searchStudyOnceWithMemberParticipation_when_takes_attendance() { long studyOnceId = searchResponse.getStudyOnceId(); long memberId = memberSaveHelper.saveMember(thumbnailImage).getId(); sut.tryJoin(memberId, studyOnceId); - syncStudyOnceRepositoryAndStudyMemberRepository(); StudyOnceSearchResponse response = sut.searchStudyOnceWithMemberParticipation( studyOnceId, memberId); @@ -148,12 +127,13 @@ void searchStudyOnceWithMemberParticipation_when_not_take_attendance() { assertThat(response.isAttendance()).isFalse(); } - @Test - @DisplayName("카공 시작시간이 23시이고 종료시간이 24시(23시 59분 59초 999_999_999초)이면 카공이 생성된다.") - void exception_case1() { + @ParameterizedTest + @MethodSource("provideLocalDateTime") + @DisplayName("카공 시작시간이 23시이고 종료시간이 24시(23시 59분 59초)이면 카공이 생성된다.") + void exception_case1(LocalDateTime end) { //given LocalDateTime start = LocalDateTime.of(2999, 1, 1, 23, 0); - LocalDateTime end = LocalDateTime.of(2999, 1, 1, 23, 59, 59, 999_999_999); + // LocalDateTime end = LocalDateTime.of(2999, 1, 1, 23, 59, 59); ThumbnailImage thumbnailImage = thumbnailImageSaveHelper.saveThumbnailImage(); Member leader = memberSaveHelper.saveMember(thumbnailImage); Cafe cafe = cafeSaveHelper.saveCafeWith24For7(); @@ -162,6 +142,14 @@ void exception_case1() { assertDoesNotThrow(() -> sut.createStudy(leader.getId(), studyOnceCreateRequest)); } + static Stream provideLocalDateTime() { + return Stream.of( + Arguments.of(LocalDateTime.of(2999, 1, 1, 23, 59, 59)) + // 밑의 테스트 케이스는 마이그레이션 후 BusinessHour의 종료 시간이 999_999_000로 들어갈 때 성공한다. + // Arguments.of(LocalDateTime.of(2999, 1, 1, 23, 59, 59, 999_999_000)) + ); + } + @Test @DisplayName("카공 시작은 현재 시간으로부터 최소 3시간이후여야 한다.") void study_starts_3hours_after_now() { @@ -297,8 +285,7 @@ static Stream provideLocalDateTime2() { @DisplayName("카페 영업시간 밖의 시간에 카공을 만들 수 없다.") void study_can_not_start_outside_cafe_business_hours(LocalDateTime start, LocalDateTime end) { //given - List businessHours = makeBusinessHourWith7daysFrom9To21(); - Cafe cafe = cafeSaveHelper.saveCafeWithBusinessHour(businessHours); + Cafe cafe = cafeSaveHelper.saveCafeWith7daysFrom9To21(); ThumbnailImage thumbnailImage = thumbnailImageSaveHelper.saveThumbnailImage(); Member leader = memberSaveHelper.saveMember(thumbnailImage); StudyOnceCreateRequest studyOnceCreateRequest = makeStudyOnceCreateRequest(start, end, cafe.getId()); @@ -320,7 +307,7 @@ static Stream provideStartAndEndDateTime1() { ), Arguments.of( LocalDateTime.of(2999, 1, 1, 20, 0), - LocalDateTime.of(2999, 1, 1, 21, 0, 0, 1) + LocalDateTime.of(2999, 1, 1, 21, 0, 1) ), Arguments.of( LocalDateTime.of(2999, 1, 1, 20, 59, 59, 999_999_999), @@ -334,8 +321,7 @@ static Stream provideStartAndEndDateTime1() { @DisplayName("카페 영업시간 내의 시간에 카공을 만들 수 있다.") void study_can_start_between_cafe_business_hours(LocalDateTime start, LocalDateTime end) { //given - List businessHours = makeBusinessHourWith7daysFrom9To21(); - Cafe cafe = cafeSaveHelper.saveCafeWithBusinessHour(businessHours); + Cafe cafe = cafeSaveHelper.saveCafeWith7daysFrom9To21(); ThumbnailImage thumbnailImage = thumbnailImageSaveHelper.saveThumbnailImage(); Member leader = memberSaveHelper.saveMember(thumbnailImage); StudyOnceCreateRequest studyOnceCreateRequest = makeStudyOnceCreateRequest(start, end, cafe.getId()); @@ -356,17 +342,6 @@ static Stream provideStartAndEndDateTime2() { ); } - private List makeBusinessHourWith7daysFrom9To21() { - List daysOfWeek = List.of("MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY", "SATURDAY", "SUNDAY"); - List businessHours = new ArrayList<>(); - for (String day : daysOfWeek) { - businessHours.add( - createBusinessHourWithDayAndTime(day, LocalTime.of(9, 0), LocalTime.of(21, 0)) - ); - } - return businessHours; - } - @Test @DisplayName("카공이 시작하기전에 카공 참여를 취소할 수 있다.") void member_can_cancel_study_before_starts() { @@ -382,8 +357,8 @@ void member_can_cancel_study_before_starts() { //when sut.tryQuit(member.getId(), studyOnce.getId()); //then - StudyOnce result = studyOnceRepository.findById(studyOnce.getId()).get(); - assertThat(result.getStudyMembers().size()).isEqualTo(1); + List result = studyMemberRepository.findAll(); + assertThat(result.size()).isEqualTo(1); } @Test @@ -420,7 +395,7 @@ void leader_can_not_check_attendance_10min_before_start() { Member member = memberSaveHelper.saveMember(thumbnailImage); StudyOnce studyOnce = studyOnceSaveHelper.saveStudyOnceWithTime(cafe, leader, start, end); sut.tryJoin(member.getId(), studyOnce.getId()); - LocalDateTime attendanceUpdateTime = start.plusMinutes(10).minusNanos(1); + LocalDateTime attendanceUpdateTime = start.plusMinutes(10).minusSeconds(1); //when assertThatThrownBy( () -> sut.updateAttendance(leader.getId(), studyOnce.getId(), member.getId(), NO, attendanceUpdateTime)) @@ -462,7 +437,7 @@ void leader_can_not_check_attendance_after_half_whole_study_time() { Member member = memberSaveHelper.saveMember(thumbnailImage); StudyOnce studyOnce = studyOnceSaveHelper.saveStudyOnceWithTime(cafe, leader, start, end); sut.tryJoin(member.getId(), studyOnce.getId()); - LocalDateTime attendanceUpdateTime = start.plusHours(2).plusNanos(1); + LocalDateTime attendanceUpdateTime = start.plusHours(2).plusSeconds(1); //when assertThatThrownBy( () -> sut.updateAttendance(leader.getId(), studyOnce.getId(), member.getId(), NO, attendanceUpdateTime)) @@ -560,8 +535,7 @@ void non_leader_can_not_update_study_details() { @DisplayName("카공 시간 변경시 카공 시간은 카페 영업시간내에 포함되어야 한다.") void study_time_must_be_within_cafe_business_hours(LocalDateTime start, LocalDateTime end) { //given - List businessHours = makeBusinessHourWith7daysFrom9To21(); - Cafe cafe = cafeSaveHelper.saveCafeWithBusinessHour(businessHours); + Cafe cafe = cafeSaveHelper.saveCafeWith7daysFrom9To21(); ThumbnailImage thumbnailImage = thumbnailImageSaveHelper.saveThumbnailImage(); Member leader = memberSaveHelper.saveMember(thumbnailImage); StudyOnce studyOnce = studyOnceSaveHelper.saveStudyOnceWithTime(cafe, leader, @@ -585,11 +559,11 @@ static Stream provideStartAndEndDateTime3() { ), Arguments.of( LocalDateTime.of(2999, 1, 1, 8, 0), - LocalDateTime.of(2999, 1, 1, 9, 0, 0, 1) + LocalDateTime.of(2999, 1, 1, 9, 0, 0, 100_000_000) ), Arguments.of( LocalDateTime.of(2999, 1, 1, 20, 0), - LocalDateTime.of(2999, 1, 1, 21, 0, 0, 1) + LocalDateTime.of(2999, 1, 1, 21, 0, 1) ), Arguments.of( LocalDateTime.of(2999, 1, 1, 20, 59, 59, 999_999_999), @@ -603,8 +577,7 @@ static Stream provideStartAndEndDateTime3() { @DisplayName("카공 시간 변경시 카공 시간은 카페 영업시간내에 포함된다.") void study_time_is_within_cafe_business_hours(LocalDateTime start, LocalDateTime end) { //given - List businessHours = makeBusinessHourWith7daysFrom9To21(); - Cafe cafe = cafeSaveHelper.saveCafeWithBusinessHour(businessHours); + Cafe cafe = cafeSaveHelper.saveCafeWith7daysFrom9To21(); ThumbnailImage thumbnailImage = thumbnailImageSaveHelper.saveThumbnailImage(); Member leader = memberSaveHelper.saveMember(thumbnailImage); StudyOnce studyOnce = studyOnceSaveHelper.saveStudyOnceWithTime(cafe, leader, @@ -646,7 +619,7 @@ void update_location_and_count_with_participants() { StudyOnceUpdateRequest request = new StudyOnceUpdateRequest(cafeId2, "변경된카공이름", start.plusHours(5), start.plusHours(6), 5, false, "오픈채팅방 링크"); //when - sut.updateStudyOncePartially(leader.getId(), studyOnce.getId(), request, LocalDateTime.now()); + sut.updateStudyOncePartially(leader.getId(), studyOnce.getId(), request); //then StudyOnce result = studyOnceRepository.findById(studyOnce.getId()).get(); assertAll( @@ -673,7 +646,7 @@ void non_leader_can_not_update_study_details_partially() { null, 5, true, null); //then assertThatThrownBy( - () -> sut.updateStudyOncePartially(member.getId(), studyOnce.getId(), request, LocalDateTime.now())) + () -> sut.updateStudyOncePartially(member.getId(), studyOnce.getId(), request)) .isInstanceOf(CafegoryException.class) .hasMessage(STUDY_ONCE_LEADER_PERMISSION_DENIED.getErrorMessage()); } diff --git a/src/test/java/com/example/demo/utils/DatabaseCleanup.java b/src/test/java/com/example/demo/utils/DatabaseCleanup.java new file mode 100644 index 0000000..df100c7 --- /dev/null +++ b/src/test/java/com/example/demo/utils/DatabaseCleanup.java @@ -0,0 +1,80 @@ +package com.example.demo.utils; + +import static org.assertj.core.api.Assertions.*; + +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.util.List; +import java.util.stream.Collectors; + +import javax.annotation.PostConstruct; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.Table; +import javax.persistence.metamodel.EntityType; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.example.demo.util.TruncatedTimeUtil; + +@Service +public class DatabaseCleanup { + + @PersistenceContext + private EntityManager em; + private List tableNames; + + @PostConstruct + public void afterPropertiesSet() { + tableNames = em.getMetamodel().getEntities().stream() + .map(this::getTableName) + .collect(Collectors.toList()); + } + + private String getTableName(EntityType entityType) { + Class javaType = entityType.getJavaType(); + // @Table 어노테이션이 있는 경우 테이블 이름 가져오기 + if (javaType.isAnnotationPresent(Table.class)) { + Table table = javaType.getAnnotation(Table.class); + return table.name(); + } + // @Table 어노테이션이 없는 경우 엔티티 이름에서 테이블 이름으로 변환 + return convertCamelCaseToSnakeCase(entityType.getName()); + } + + @Transactional + public void execute() { + em.flush(); + + for (String tableName : tableNames) { + em.createNativeQuery("TRUNCATE TABLE " + tableName).executeUpdate(); + } + } + + private String convertCamelCaseToSnakeCase(String input) { + if (input == null) { + return null; + } + return input.replaceAll("([a-z])([A-Z]+)", "$1_$2").toLowerCase(); + } + + static class TruncatedTimeUtilTest { + + @Test + @DisplayName("나노초에서 초단위로 절삭한다.") + void convert_nano_to_micro_time() { + LocalTime result = TruncatedTimeUtil.truncateTimeToSecond(LocalTime.of(23, 59, 59, 999_999_999)); + assertThat(result).isEqualTo(LocalTime.of(23, 59, 59)); + } + + @Test + @DisplayName("나노초에서 초단위로 절삭한다.") + void convert_nano_to_micro_date_time() { + LocalDateTime result = TruncatedTimeUtil.truncateDateTimeToSecond(LocalDateTime.MAX); + assertThat(result).isEqualTo(LocalDateTime.of(999999999, 12, 31, 23, 59, 59)); + } + } +} diff --git a/src/test/resources/application.yml b/src/test/resources/application-test.yml similarity index 78% rename from src/test/resources/application.yml rename to src/test/resources/application-test.yml index 1ef8a4c..96533ff 100644 --- a/src/test/resources/application.yml +++ b/src/test/resources/application-test.yml @@ -2,16 +2,19 @@ server: port: 8080 spring: datasource: #연결할 디비의 이름 - driver-class-name: org.h2.Driver #디비 종류 - url: jdbc:h2:~/test - username: "sa" - password: "" + driver-class-name: org.mariadb.jdbc.Driver #디비 종류 + url: jdbc:mariadb://localhost:3306/cafegory_test + # username: cafegory + username: cafegory_test + # password: cafegory!Q@W#E + password: 1234 jpa: #jpa 종류 hibernate: ddl-auto: create properties: hibernate: format_sql: true #이쁘게 해줌 + dialect: org.hibernate.dialect.MariaDBDialect mail: host: smtp.gmail.com port: 587