From a9947933c719c513e22d08992e152be1d1df579f Mon Sep 17 00:00:00 2001 From: Eunhee Baek <78892355+ehbeak@users.noreply.github.com> Date: Sat, 20 Apr 2024 18:08:56 +0900 Subject: [PATCH 01/74] migrate first mission code --- README.md | 95 ++++++++++++++++ .../roomescape/RoomescapeApplication.java | 2 - .../controller/ReservationController.java | 42 +++++++ .../controller/ReservationTimeController.java | 42 +++++++ .../controller/StaticPageController.java | 22 ++++ .../request/ReservationRequest.java | 6 + .../request/ReservationTimeRequest.java | 6 + .../java/roomescape/model/Reservation.java | 43 +++++++ .../roomescape/model/ReservationTime.java | 29 +++++ .../roomescape/repository/ReservationDAO.java | 67 +++++++++++ .../repository/ReservationRepository.java | 12 ++ .../repository/ReservationTimeDAO.java | 60 ++++++++++ .../repository/ReservationTimeRepository.java | 14 +++ .../service/ReservationService.java | 35 ++++++ .../service/ReservationTimeService.java | 34 ++++++ src/main/resources/application.properties | 2 + src/main/resources/schema.sql | 20 ++++ .../controller/ReservationControllerTest.java | 103 +++++++++++++++++ .../ReservationTimeControllerTest.java | 70 ++++++++++++ .../java/roomescape/dao/DBConnectionTest.java | 50 +++++++++ .../repository/ReservationDAOTest.java | 105 ++++++++++++++++++ .../repository/ReservationTimeDAOTest.java | 83 ++++++++++++++ .../FakeReservationTimeRepository.java | 46 ++++++++ .../service/ReservationServiceTest.java | 75 +++++++++++++ .../service/ReservationTimeServiceTest.java | 45 ++++++++ 25 files changed, 1106 insertions(+), 2 deletions(-) create mode 100644 README.md create mode 100644 src/main/java/roomescape/controller/ReservationController.java create mode 100644 src/main/java/roomescape/controller/ReservationTimeController.java create mode 100644 src/main/java/roomescape/controller/StaticPageController.java create mode 100644 src/main/java/roomescape/controller/request/ReservationRequest.java create mode 100644 src/main/java/roomescape/controller/request/ReservationTimeRequest.java create mode 100644 src/main/java/roomescape/model/Reservation.java create mode 100644 src/main/java/roomescape/model/ReservationTime.java create mode 100644 src/main/java/roomescape/repository/ReservationDAO.java create mode 100644 src/main/java/roomescape/repository/ReservationRepository.java create mode 100644 src/main/java/roomescape/repository/ReservationTimeDAO.java create mode 100644 src/main/java/roomescape/repository/ReservationTimeRepository.java create mode 100644 src/main/java/roomescape/service/ReservationService.java create mode 100644 src/main/java/roomescape/service/ReservationTimeService.java create mode 100644 src/main/resources/schema.sql create mode 100644 src/test/java/roomescape/controller/ReservationControllerTest.java create mode 100644 src/test/java/roomescape/controller/ReservationTimeControllerTest.java create mode 100644 src/test/java/roomescape/dao/DBConnectionTest.java create mode 100644 src/test/java/roomescape/repository/ReservationDAOTest.java create mode 100644 src/test/java/roomescape/repository/ReservationTimeDAOTest.java create mode 100644 src/test/java/roomescape/service/FakeReservationTimeRepository.java create mode 100644 src/test/java/roomescape/service/ReservationServiceTest.java create mode 100644 src/test/java/roomescape/service/ReservationTimeServiceTest.java diff --git a/README.md b/README.md new file mode 100644 index 0000000000..4a57877f84 --- /dev/null +++ b/README.md @@ -0,0 +1,95 @@ + +# 요구 사항 +### API 구현하기 +- [x] `localhost:8080/admin` get 요청 시 어드민 메인 페이지가 응답할 수 있다. +- [x] `localhost:8080` get 요청 시 어드민 메인 페이지가 응답할 수 있다. +- [x] `/admin/reservation` get 요청 시 예약 관리 페이지가 응답할 수 있다. +- [x] 예약 관리 페이지 응답 시, 현재 예약 목록을 함께 보여준다. +- [x] `/reservations` get 요청시 예약 목록을 조회한다. + - [x] 저장된 예약을 조회할 때 데이터베이스에 있는 값을 조회한다. +- [x] `/admin/reservation` post 요청 시 예약을 추가한다. + - [x] 예약을 추가할 때 데이터베이스에 값을 추가한다. +- [x] `/reservations/{id}` delete 요청 시 예약을 삭제한다. + - [x] id 값이 없는 경우 예외를 발생시킨다. + - [x] 예약을 삭제할 때 데이터베이스에 값을 삭제한다. +- [x] `/times` post 요청 시 시간을 추가한다. +- [x] `/times` get 요청 시 모든 시간을 조회한다. +- [x] `/times/{id}` delete 요청 시 해당 시간을 삭제한다. + +### 데이터베이스 +- [x] h2 데이터베이스와 연동한다. + - [x] gradle 의존성 추가한다. + - [x] 테이블 생성을 위한 스키마 정의한다. + - [x] h2 데이터베이스 콘솔 기능 활성화한다. + +### 콘솔 UI 지원 +- [x] 시간, 예약 관리 기능을 콘솔에서도 사용할 수 있도록 콘솔 UI를 추가합니다. +- [x] 콘솔 UI를 사용해 생성되는 데이터는 데이터베이스가 아닌 메모리에 저장합니다. + +``` +방탈출 관리 시스템 기능입니다. +1 방탈출 예약 조회 +2 방탈출 예약시간 조회 +3 방탈출 예약 추가 +4 방탈출 예약시간 추가 +5 방탈출 예약 삭제 +6 방탈출 예약시간 삭제 +7 종료 + +이용하실 기능의 번호를 입력해주세요 : 1 +방탈출 예약 내역입니다. +예약번호 예약자 날짜 시간 +1 파랑 2024-4-12 10:00:00 +2 배키 2024-4-13 11:00:00 +2 네오 2024-4-13 16:30:00 + + +이용하실 기능의 번호를 입력해주세요 : 2 +방탈출 시간 내역입니다. +순서 시간 +1 10:00:00 +2 11:00:00 + + +이용하실 기능의 번호를 입력해주세요 : 3 +방탈출 예약 화면입니다. +현재 방탈출 시간 내역입니다. +순서 시간 +1 10:00:00 +2 11:00:00 +원하는 시간에 맞는 순서를 입력해주세요 : 1 +예약자 이름을 입력해주세요 : 배키 +날짜를 입력해주세요. (ex. 2024-4-14) : 2024-5-12 +예약되었습니다. + + +이용하실 기능의 번호를 입력해주세요 : 4 +방탈출 예약시간 추가 화면입니다. +추가할 예약시간을 입력해주세요 (ex. 11:00:00) : 13:10:00 +예약시간이 추가되었습니다. + + +이용하실 기능의 번호를 입력해주세요 : 5 +방탈출 삭제 화면입니다. +현재 방탈출 예약 내역입니다. +예약번호 예약자 날짜 시간 +1 파랑 2024-4-12 10:00:00 +2 배키 2024-4-13 11:00:00 +3 네오 2024-4-13 16:30:00 +삭제하고 싶은 방탈출 예약번호를 입력해주세요 : 2 +방탈출 예약이 삭제되었습니다. + + +이용하실 기능의 번호를 입력해주세요 : 6 +방탈출 예약시간 삭제 화면입니다. +현재 방탈출 시간 내역입니다. +순서 시간 +1 10:00:00 +2 11:00:00 +삭제하고 싶은 예약시간의 순서를 입력해주세요 : 2 +예약시간이 삭제되었습니다. + + +이용하실 기능의 번호를 입력해주세요 : 5 +방탈출 예약관리 기능이 종료되었습니다. +``` diff --git a/src/main/java/roomescape/RoomescapeApplication.java b/src/main/java/roomescape/RoomescapeApplication.java index 5fcfdde5d6..55dcd5aa0d 100644 --- a/src/main/java/roomescape/RoomescapeApplication.java +++ b/src/main/java/roomescape/RoomescapeApplication.java @@ -2,12 +2,10 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; - @SpringBootApplication public class RoomescapeApplication { public static void main(String[] args) { SpringApplication.run(RoomescapeApplication.class, args); } - } diff --git a/src/main/java/roomescape/controller/ReservationController.java b/src/main/java/roomescape/controller/ReservationController.java new file mode 100644 index 0000000000..a84d043a4f --- /dev/null +++ b/src/main/java/roomescape/controller/ReservationController.java @@ -0,0 +1,42 @@ +package roomescape.controller; + +import java.net.URI; +import java.util.List; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; +import roomescape.controller.request.ReservationRequest; +import roomescape.model.Reservation; +import roomescape.service.ReservationService; + +@RestController +public class ReservationController { + + private final ReservationService reservationService; + + public ReservationController(ReservationService reservationService) { + this.reservationService = reservationService; + } + + + @GetMapping("/reservations") + public ResponseEntity> getReservations() { + return ResponseEntity.ok(reservationService.findAllReservations()); + } + + @PostMapping("/reservations") + public ResponseEntity createReservation(@RequestBody ReservationRequest request) { + Reservation reservation = reservationService.addReservation(request); + return ResponseEntity.created(URI.create("/reservations/" + reservation.getId())).body(reservation); + } + + @DeleteMapping("/reservations/{id}") + public ResponseEntity deleteReservation(@PathVariable("id") long id) { + reservationService.deleteReservation(id); + return ResponseEntity.noContent().build(); + } +} diff --git a/src/main/java/roomescape/controller/ReservationTimeController.java b/src/main/java/roomescape/controller/ReservationTimeController.java new file mode 100644 index 0000000000..bdd4f546b2 --- /dev/null +++ b/src/main/java/roomescape/controller/ReservationTimeController.java @@ -0,0 +1,42 @@ +package roomescape.controller; + +import java.net.URI; +import java.util.List; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; +import roomescape.controller.request.ReservationTimeRequest; +import roomescape.model.ReservationTime; +import roomescape.service.ReservationTimeService; + +@RestController +public class ReservationTimeController { + + private final ReservationTimeService reservationTimeService; + + public ReservationTimeController(ReservationTimeService reservationTimeService) { + this.reservationTimeService = reservationTimeService; + } + + @GetMapping("/times") + public ResponseEntity> getReservationTimes() { + List reservationTimes = reservationTimeService.findAllReservationTimes(); + return ResponseEntity.ok(reservationTimes); + } + + @PostMapping("/times") + public ResponseEntity createReservationTime(@RequestBody ReservationTimeRequest request) { + ReservationTime reservationTime = reservationTimeService.addReservationTime(request); + return ResponseEntity.created(URI.create("/times/" + reservationTime.getId())).body(reservationTime); + } + + @DeleteMapping("/times/{id}") + public ResponseEntity deleteReservationTime(@PathVariable("id") long id) { + reservationTimeService.deleteReservationTime(id); + return ResponseEntity.ok().build(); + } +} diff --git a/src/main/java/roomescape/controller/StaticPageController.java b/src/main/java/roomescape/controller/StaticPageController.java new file mode 100644 index 0000000000..98bcedd65f --- /dev/null +++ b/src/main/java/roomescape/controller/StaticPageController.java @@ -0,0 +1,22 @@ +package roomescape.controller; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; + +@Controller +public class StaticPageController { + @GetMapping(path = {"/", "/admin"}) + public String getAdminPage() { + return "admin/index"; + } + + @GetMapping("/admin/reservation") + public String getReservationPage() { + return "admin/reservation"; + } + + @GetMapping("/admin/time") + public String getReservationTimePage() { + return "admin/time"; + } +} diff --git a/src/main/java/roomescape/controller/request/ReservationRequest.java b/src/main/java/roomescape/controller/request/ReservationRequest.java new file mode 100644 index 0000000000..76e15acd02 --- /dev/null +++ b/src/main/java/roomescape/controller/request/ReservationRequest.java @@ -0,0 +1,6 @@ +package roomescape.controller.request; + +import java.time.LocalDate; + +public record ReservationRequest(LocalDate date, String name, long timeId) { +} diff --git a/src/main/java/roomescape/controller/request/ReservationTimeRequest.java b/src/main/java/roomescape/controller/request/ReservationTimeRequest.java new file mode 100644 index 0000000000..6981d408af --- /dev/null +++ b/src/main/java/roomescape/controller/request/ReservationTimeRequest.java @@ -0,0 +1,6 @@ +package roomescape.controller.request; + +import java.time.LocalTime; + +public record ReservationTimeRequest(LocalTime startAt) { +} diff --git a/src/main/java/roomescape/model/Reservation.java b/src/main/java/roomescape/model/Reservation.java new file mode 100644 index 0000000000..5105c5f180 --- /dev/null +++ b/src/main/java/roomescape/model/Reservation.java @@ -0,0 +1,43 @@ +package roomescape.model; + +import java.time.LocalDate; + +public class Reservation { + + private long id; + private String name; + private LocalDate date; + private ReservationTime time; + + private Reservation() { + } + + public Reservation(long id, String name, LocalDate date, ReservationTime time) { + this.id = id; + this.name = name; + this.date = date; + this.time = time; + } + + public Reservation(String name, LocalDate date, ReservationTime time) { + this.name = name; + this.date = date; + this.time = time; + } + + public long getId() { + return id; + } + + public String getName() { + return name; + } + + public LocalDate getDate() { + return date; + } + + public ReservationTime getTime() { + return time; + } +} diff --git a/src/main/java/roomescape/model/ReservationTime.java b/src/main/java/roomescape/model/ReservationTime.java new file mode 100644 index 0000000000..9a2b6eeafb --- /dev/null +++ b/src/main/java/roomescape/model/ReservationTime.java @@ -0,0 +1,29 @@ +package roomescape.model; + +import java.time.LocalTime; + +public class ReservationTime { + + private long id; + private LocalTime startAt; + + private ReservationTime() { + } + + public ReservationTime(LocalTime startAt) { + this.startAt = startAt; + } + + public ReservationTime(long id, LocalTime startAt) { + this.id = id; + this.startAt = startAt; + } + + public long getId() { + return id; + } + + public LocalTime getStartAt() { + return startAt; + } +} diff --git a/src/main/java/roomescape/repository/ReservationDAO.java b/src/main/java/roomescape/repository/ReservationDAO.java new file mode 100644 index 0000000000..c4f20dbac3 --- /dev/null +++ b/src/main/java/roomescape/repository/ReservationDAO.java @@ -0,0 +1,67 @@ +package roomescape.repository; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.sql.DataSource; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.simple.SimpleJdbcInsert; +import org.springframework.stereotype.Repository; +import roomescape.model.Reservation; +import roomescape.model.ReservationTime; + +@Repository +public class ReservationDAO implements ReservationRepository { + + private final JdbcTemplate jdbcTemplate; + + private SimpleJdbcInsert insertActor; + + public ReservationDAO(JdbcTemplate jdbcTemplate, DataSource dataSource) { + this.jdbcTemplate = jdbcTemplate; + this.insertActor = new SimpleJdbcInsert(dataSource) + .withTableName("reservation") + .usingGeneratedKeyColumns("id"); + } + + @Override + public List getAllReservations() { + String sql = """ + select + r.id as reservation_id, + r.name, + r.date, + t.id as time_id, + t.start_at as time_start_at + from reservation as r + inner join reservation_time as t + on r.time_id = t.id + """; + return jdbcTemplate.query(sql, (resultSet, rowNum) -> + new Reservation( + resultSet.getLong("reservation_id"), + resultSet.getString("name"), + resultSet.getDate("date").toLocalDate(), + new ReservationTime( + resultSet.getLong("time_id"), + resultSet.getTime("time_start_at").toLocalTime() + ) + )); + } + + @Override + public Reservation addReservation(Reservation reservation) { + Map parameters = new HashMap<>(3); + parameters.put("name", reservation.getName()); + parameters.put("date", reservation.getDate()); + parameters.put("time_id", reservation.getTime().getId()); + Number newId = insertActor.executeAndReturnKey(parameters); + return new Reservation(newId.longValue(), reservation.getName(), reservation.getDate(), reservation.getTime()); + } + + @Override + public long deleteReservation(long id) { + String sql = "delete from reservation where id = ?"; + return jdbcTemplate.update(sql, id); + } +} diff --git a/src/main/java/roomescape/repository/ReservationRepository.java b/src/main/java/roomescape/repository/ReservationRepository.java new file mode 100644 index 0000000000..c09e2bee1c --- /dev/null +++ b/src/main/java/roomescape/repository/ReservationRepository.java @@ -0,0 +1,12 @@ +package roomescape.repository; + +import java.util.List; +import roomescape.model.Reservation; + +public interface ReservationRepository { + List getAllReservations(); + + Reservation addReservation(Reservation reservation); + + long deleteReservation(long id); +} diff --git a/src/main/java/roomescape/repository/ReservationTimeDAO.java b/src/main/java/roomescape/repository/ReservationTimeDAO.java new file mode 100644 index 0000000000..33797870d5 --- /dev/null +++ b/src/main/java/roomescape/repository/ReservationTimeDAO.java @@ -0,0 +1,60 @@ +package roomescape.repository; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.sql.DataSource; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.simple.SimpleJdbcInsert; +import org.springframework.stereotype.Repository; +import roomescape.model.ReservationTime; + +@Repository +public class ReservationTimeDAO implements ReservationTimeRepository { + + private final JdbcTemplate jdbcTemplate; + + private SimpleJdbcInsert insertActor; + + public ReservationTimeDAO(JdbcTemplate jdbcTemplate, DataSource dataSource) { + this.jdbcTemplate = jdbcTemplate; + this.insertActor = new SimpleJdbcInsert(dataSource) + .withTableName("reservation_time") + .usingGeneratedKeyColumns("id"); + } + + @Override + public List findAllReservationTimes() { + String sql = "select id, start_at from reservation_time"; + return jdbcTemplate.query(sql, (resultSet, rowNum) -> + new ReservationTime( + resultSet.getLong("id"), + resultSet.getTime("start_at").toLocalTime() + )); + } + + @Override + public ReservationTime findReservationById(long id) { + String sql = "select * from reservation_time where id = ?"; + return jdbcTemplate.queryForObject(sql, (resultSet, rowNum) -> + new ReservationTime( + resultSet.getLong("id"), + resultSet.getTime("start_at").toLocalTime() + ), id); + } + + @Override + public ReservationTime addReservationTime(ReservationTime reservationTime) { + Map parameters = new HashMap<>(1); + parameters.put("start_at", reservationTime.getStartAt()); + Number newId = insertActor.executeAndReturnKey(parameters); + return new ReservationTime(newId.longValue(), reservationTime.getStartAt()); + } + + @Override + public void deleteReservationTime(long id) { + String sql = "delete from reservation_time where id = ?"; + jdbcTemplate.update(sql, id); + + } +} diff --git a/src/main/java/roomescape/repository/ReservationTimeRepository.java b/src/main/java/roomescape/repository/ReservationTimeRepository.java new file mode 100644 index 0000000000..6eb2070c69 --- /dev/null +++ b/src/main/java/roomescape/repository/ReservationTimeRepository.java @@ -0,0 +1,14 @@ +package roomescape.repository; + +import java.util.List; +import roomescape.model.ReservationTime; + +public interface ReservationTimeRepository { + List findAllReservationTimes(); + + ReservationTime findReservationById(long id); + + ReservationTime addReservationTime(ReservationTime reservationTime); + + void deleteReservationTime(long id); +} diff --git a/src/main/java/roomescape/service/ReservationService.java b/src/main/java/roomescape/service/ReservationService.java new file mode 100644 index 0000000000..2b8dc29ecf --- /dev/null +++ b/src/main/java/roomescape/service/ReservationService.java @@ -0,0 +1,35 @@ +package roomescape.service; + +import java.util.List; +import org.springframework.stereotype.Service; +import roomescape.controller.request.ReservationRequest; +import roomescape.model.Reservation; +import roomescape.model.ReservationTime; +import roomescape.repository.ReservationRepository; +import roomescape.repository.ReservationTimeRepository; + +@Service +public class ReservationService { + + private final ReservationRepository reservationRepository; + private final ReservationTimeRepository reservationTimeDAO; + + public ReservationService(ReservationRepository reservationRepository, + ReservationTimeRepository reservationTimeRepository) { + this.reservationRepository = reservationRepository; + this.reservationTimeDAO = reservationTimeRepository; + } + + public List findAllReservations() { + return reservationRepository.getAllReservations(); + } + + public Reservation addReservation(ReservationRequest request) { + ReservationTime reservationTime = reservationTimeDAO.findReservationById(request.timeId()); + return reservationRepository.addReservation(new Reservation(request.name(), request.date(), reservationTime)); + } + + public void deleteReservation(long id) { + reservationRepository.deleteReservation(id); + } +} diff --git a/src/main/java/roomescape/service/ReservationTimeService.java b/src/main/java/roomescape/service/ReservationTimeService.java new file mode 100644 index 0000000000..56341dd74a --- /dev/null +++ b/src/main/java/roomescape/service/ReservationTimeService.java @@ -0,0 +1,34 @@ +package roomescape.service; + +import java.util.List; +import org.springframework.stereotype.Service; +import roomescape.controller.request.ReservationTimeRequest; +import roomescape.model.ReservationTime; +import roomescape.repository.ReservationTimeRepository; + +@Service +public class ReservationTimeService { + + private final ReservationTimeRepository reservationTimeRepository; + + public ReservationTimeService(ReservationTimeRepository reservationTimeRepository) { + this.reservationTimeRepository = reservationTimeRepository; + } + + public List findAllReservationTimes() { + return reservationTimeRepository.findAllReservationTimes(); + } + + public ReservationTime addReservationTime(ReservationTimeRequest request) { + ReservationTime reservationTime = new ReservationTime(request.startAt()); + return reservationTimeRepository.addReservationTime(reservationTime); + } + + public ReservationTime findReservationTime(long id) { + return reservationTimeRepository.findReservationById(id); + } + + public void deleteReservationTime(long id) { + reservationTimeRepository.deleteReservationTime(id); + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index e69de29bb2..b53e73970d 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -0,0 +1,2 @@ +spring.h2.console.enabled=true +spring.datasource.url=jdbc:h2:mem:test diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql new file mode 100644 index 0000000000..dd05ed17f4 --- /dev/null +++ b/src/main/resources/schema.sql @@ -0,0 +1,20 @@ +CREATE TABLE reservation_time +( + id BIGINT NOT NULL AUTO_INCREMENT, + start_at VARCHAR(255) NOT NULL, + PRIMARY KEY (id) +); + +CREATE TABLE reservation +( + id BIGINT NOT NULL AUTO_INCREMENT, + name VARCHAR(255) NOT NULL, + date VARCHAR(255) NOT NULL, + time_id BIGINT, + PRIMARY KEY (id), + FOREIGN KEY (time_id) REFERENCES reservation_time (id) +); + +INSERT INTO reservation_time (start_at) VALUES ('10:00'); +INSERT INTO reservation_time (start_at) VALUES ('11:00'); + diff --git a/src/test/java/roomescape/controller/ReservationControllerTest.java b/src/test/java/roomescape/controller/ReservationControllerTest.java new file mode 100644 index 0000000000..a78187653f --- /dev/null +++ b/src/test/java/roomescape/controller/ReservationControllerTest.java @@ -0,0 +1,103 @@ +package roomescape.controller; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +import io.restassured.RestAssured; +import io.restassured.http.ContentType; +import java.lang.reflect.Field; +import java.time.LocalDate; +import java.util.List; +import org.assertj.core.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.jdbc.core.JdbcTemplate; +import org.springframework.test.annotation.DirtiesContext; +import roomescape.controller.request.ReservationRequest; +import roomescape.model.Reservation; + + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) +@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) +class ReservationControllerTest { + + @Autowired + JdbcTemplate jdbcTemplate; + + @Autowired + private ReservationController reservationController; + + @Test + void should_get_reservations() { + jdbcTemplate.update("INSERT INTO reservation_time (start_at) VALUES (?)", "10:00"); + jdbcTemplate.update("INSERT INTO reservation (name, date, time_id) VALUES (?, ?, ?)", "브라운", "2023-08-05", "1"); + + List reservations = RestAssured.given().log().all() + .when().get("/reservations") + .then().log().all() + .statusCode(200).extract() + .jsonPath().getList(".", Reservation.class); + + Integer count = jdbcTemplate.queryForObject("SELECT count(1) from reservation", Integer.class); + + Assertions.assertThat(reservations).hasSize(count); + } + + @DisplayName("예약을 추가할 수 있다.") + @Test + void should_insert_reservation() { + Integer count1 = jdbcTemplate.queryForObject("SELECT count(1) from reservation", Integer.class); + System.out.println("count1 = " + count1); + ReservationRequest request = new ReservationRequest( + LocalDate.of(2023, 8, 5), + "브라운", + 1); + + RestAssured.given().log().all() + .contentType(ContentType.JSON) + .body(request) + .when().post("/reservations") + .then().log().all() + .statusCode(201) + .header("Location", "/reservations/1"); + + Integer count = jdbcTemplate.queryForObject("SELECT count(1) from reservation", Integer.class); + System.out.println("count = " + count); + assertThat(count).isEqualTo(1); + } + + @DisplayName("존재하는 예약이라면 예약을 삭제할 수 있다.") + @Test + void should_delete_reservation_when_reservation_exist() { + jdbcTemplate.update( + "INSERT INTO reservation_time (start_at) VALUES (?)", + "10:00"); + jdbcTemplate.update( + "INSERT INTO reservation (name, date, time_id) VALUES (?, ?, ?)", + "브라운", "2023-08-05", "1"); + + RestAssured.given().log().all() + .when().delete("/reservations/1") + .then().log().all() + .statusCode(204); + + Integer countAfterDelete = jdbcTemplate.queryForObject("SELECT count(1) from reservation", Integer.class); + assertThat(countAfterDelete).isZero(); + } + + @DisplayName("컨트롤러에 JdbcTemplate 필드가 존재하지 않는다.") + @Test + void should_not_exist_JdbcTemplate_field() { + boolean isJdbcTemplateInjected = false; + + for (Field field : reservationController.getClass().getDeclaredFields()) { + if (field.getType().equals(JdbcTemplate.class)) { + isJdbcTemplateInjected = true; + break; + } + } + + assertThat(isJdbcTemplateInjected).isFalse(); + } +} diff --git a/src/test/java/roomescape/controller/ReservationTimeControllerTest.java b/src/test/java/roomescape/controller/ReservationTimeControllerTest.java new file mode 100644 index 0000000000..9b465fe612 --- /dev/null +++ b/src/test/java/roomescape/controller/ReservationTimeControllerTest.java @@ -0,0 +1,70 @@ +package roomescape.controller; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +import io.restassured.RestAssured; +import io.restassured.http.ContentType; +import java.time.LocalTime; +import java.util.List; +import org.assertj.core.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.jdbc.core.JdbcTemplate; +import org.springframework.test.annotation.DirtiesContext; +import roomescape.controller.request.ReservationTimeRequest; +import roomescape.model.ReservationTime; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) +@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) +class ReservationTimeControllerTest { + + @Autowired + JdbcTemplate jdbcTemplate; + + @DisplayName("모든 예약 시간을 조회한다") + @Test + void should_get_reservation_times() { + jdbcTemplate.update("INSERT INTO reservation_time (start_at) values (?)", "10:00"); + + List reservationTimes = RestAssured.given().log().all() + .when().get("/times") + .then().log().all() + .statusCode(200).extract() + .jsonPath().getList(".", ReservationTime.class); + + Integer count = jdbcTemplate.queryForObject("SELECT count(1) from reservation_time", Integer.class); + + Assertions.assertThat(reservationTimes).hasSize(count); + } + + @DisplayName("예약 시간을 추가한다") + @Test + void should_add_reservation_times() { + ReservationTimeRequest request = new ReservationTimeRequest(LocalTime.of(10, 0)); + + RestAssured.given().log().all() + .contentType(ContentType.JSON) + .body(request) + .when().post("/times") + .then().log().all() + .statusCode(201) + .header("Location", "/times/3"); + + Integer count = jdbcTemplate.queryForObject("SELECT count(1) from reservation_time", Integer.class); + assertThat(count).isEqualTo(3); + } + + @DisplayName("예약 시간을 삭제한다") + @Test + void should_remove_reservation_time() { + RestAssured.given().log().all() + .when().delete("/times/1") + .then().log().all() + .statusCode(200); + + Integer count = jdbcTemplate.queryForObject("SELECT count(1) from reservation_time", Integer.class); + assertThat(count).isEqualTo(1); + } +} diff --git a/src/test/java/roomescape/dao/DBConnectionTest.java b/src/test/java/roomescape/dao/DBConnectionTest.java new file mode 100644 index 0000000000..c802944c63 --- /dev/null +++ b/src/test/java/roomescape/dao/DBConnectionTest.java @@ -0,0 +1,50 @@ +package roomescape.dao; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +import java.sql.Connection; +import java.sql.SQLException; +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.jdbc.core.JdbcTemplate; +import org.springframework.test.annotation.DirtiesContext; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) +@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) +class DBConnectionTest { + + @Autowired + private JdbcTemplate jdbcTemplate; + + @DisplayName("커넥션을 얻어왔는지 확인한다.") + @Test + void should_connect_is_notNull_when_getConnection() { + try (Connection connection = jdbcTemplate.getDataSource().getConnection()) { + assertThat(connection.getMetaData().getTables(null, null, "RESERVATION", null).next()).isTrue(); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + + @DisplayName("커넥션의 카탈로그가 데이터베이스인지 확인한다.") + @Test + void should_catalog_is_database__when_getConnection() { + try (Connection connection = jdbcTemplate.getDataSource().getConnection()) { + assertThat(connection.getMetaData().getTables(null, null, "RESERVATION", null).next()).isTrue(); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + + @DisplayName("연결된 데이터베이스에 RESERVATION 테이블이 있어야 한다.") + @Test + void should_table_name_is_reservation_when_getConnection() { + try (Connection connection = jdbcTemplate.getDataSource().getConnection()) { + assertThat(connection.getMetaData().getTables(null, null, "RESERVATION", null).next()).isTrue(); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/test/java/roomescape/repository/ReservationDAOTest.java b/src/test/java/roomescape/repository/ReservationDAOTest.java new file mode 100644 index 0000000000..fbd97a4334 --- /dev/null +++ b/src/test/java/roomescape/repository/ReservationDAOTest.java @@ -0,0 +1,105 @@ +package roomescape.repository; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.time.LocalDate; +import java.time.LocalTime; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.sql.DataSource; +import org.junit.jupiter.api.BeforeEach; +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.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.simple.SimpleJdbcInsert; +import org.springframework.test.annotation.DirtiesContext; +import roomescape.model.Reservation; +import roomescape.model.ReservationTime; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) +@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) +class ReservationDAOTest { + + @Autowired + JdbcTemplate jdbcTemplate; + + @Autowired + ReservationRepository reservationRepository; + + @Autowired + DataSource dataSource; + + SimpleJdbcInsert reservationTimeInsertActor; + + SimpleJdbcInsert reservationInsertActor; + + @BeforeEach + void setUp() { + jdbcTemplate.execute("TRUNCATE TABLE reservation RESTART IDENTITY"); + jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY FALSE"); + jdbcTemplate.execute("TRUNCATE TABLE reservation_time RESTART IDENTITY"); + jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY TRUE"); + + reservationTimeInsertActor = new SimpleJdbcInsert(dataSource) + .withTableName("reservation_time") + .usingGeneratedKeyColumns("id"); + reservationInsertActor = new SimpleJdbcInsert(dataSource) + .withTableName("reservation") + .usingGeneratedKeyColumns("id"); + + insertReservationTime("10:00"); + insertReservationTime("11:00"); + + insertToReservation("브라운", "2023-08-05", "1"); + insertToReservation("리사", "2023-08-01", "2"); + } + + private void insertReservationTime(String startAt) { + Map parameters = new HashMap<>(1); + parameters.put("start_at", startAt); + reservationTimeInsertActor.execute(parameters); + } + + private void insertToReservation(String name, String date, String timeId) { + Map parameters = new HashMap<>(3); + parameters.put("name", name); + parameters.put("date", date); + parameters.put("time_id", timeId); + reservationInsertActor.execute(parameters); + } + + @DisplayName("모든 예약을 조회한다") + @Test + void should_get_reservation() { + List reservations = reservationRepository.getAllReservations(); + assertThat(reservations).hasSize(2); + } + + @DisplayName("조회한 예약에 예약 시간이 존재한다.") + @Test + void should_get_reservation_times() { + List reservations = reservationRepository.getAllReservations(); + assertThat(reservations.get(0).getTime().getStartAt()).isEqualTo(LocalTime.of(10, 0)); + } + + @DisplayName("예약을 추가한다") + @Test + void should_add_reservation() { + ReservationTime reservationTime = new ReservationTime(1, LocalTime.of(10, 0)); + reservationRepository.addReservation( + new Reservation("네오", LocalDate.of(2024, 9, 1), reservationTime)); + Integer count = jdbcTemplate.queryForObject("select count(1) from reservation", Integer.class); + assertThat(count).isEqualTo(3); + } + + @DisplayName("예약을 삭제한다") + @Test + void should_delete_reservation() { + reservationRepository.deleteReservation(1); + Integer count = jdbcTemplate.queryForObject("select count(1) from reservation", Integer.class); + assertThat(count).isEqualTo(1); + } +} diff --git a/src/test/java/roomescape/repository/ReservationTimeDAOTest.java b/src/test/java/roomescape/repository/ReservationTimeDAOTest.java new file mode 100644 index 0000000000..9b561d9964 --- /dev/null +++ b/src/test/java/roomescape/repository/ReservationTimeDAOTest.java @@ -0,0 +1,83 @@ +package roomescape.repository; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.time.LocalTime; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.sql.DataSource; +import org.junit.jupiter.api.BeforeEach; +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.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.simple.SimpleJdbcInsert; +import org.springframework.test.annotation.DirtiesContext; +import roomescape.model.ReservationTime; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) +@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) +class ReservationTimeDAOTest { + + @Autowired + JdbcTemplate jdbcTemplate; + + @Autowired + DataSource dataSource; + + @Autowired + ReservationTimeDAO reservationTimeDAOImpl; + + SimpleJdbcInsert insertActor; + + @BeforeEach + void setUp() { + jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY FALSE"); + jdbcTemplate.execute("TRUNCATE TABLE reservation_time RESTART IDENTITY"); + jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY TRUE"); + + insertActor = new SimpleJdbcInsert(dataSource) + .withTableName("reservation_time") + .usingGeneratedKeyColumns("id"); + insertToReservationTime("10:00"); + insertToReservationTime("11:00"); + } + + private void insertToReservationTime(String startAt) { + Map parameters = new HashMap<>(1); + parameters.put("start_at", startAt); + insertActor.execute(parameters); + } + + @DisplayName("모든 예약 시간을 조회한다") + @Test + void should_get_reservation_times() { + List reservationTimes = reservationTimeDAOImpl.findAllReservationTimes(); + assertThat(reservationTimes).hasSize(2); + } + + @DisplayName("예약 시간을 추가한다") + @Test + void should_add_reservation_time() { + reservationTimeDAOImpl.addReservationTime(new ReservationTime(LocalTime.of(12, 0))); + Integer count = jdbcTemplate.queryForObject("select count(1) from reservation_time", Integer.class); + assertThat(count).isEqualTo(3); + } + + @DisplayName("예약 시간을 삭제한다") + @Test + void should_delete_reservation_time() { + reservationTimeDAOImpl.deleteReservationTime(1); + Integer count = jdbcTemplate.queryForObject("select count(1) from reservation_time", Integer.class); + assertThat(count).isEqualTo(1); + } + + @DisplayName("아이디에 해당하는 예약 시간을 조회한다.") + @Test + void should_get_reservation_time() { + ReservationTime reservationTime = reservationTimeDAOImpl.findReservationById(1); + assertThat(reservationTime.getStartAt()).isEqualTo(LocalTime.of(10, 0)); + } +} diff --git a/src/test/java/roomescape/service/FakeReservationTimeRepository.java b/src/test/java/roomescape/service/FakeReservationTimeRepository.java new file mode 100644 index 0000000000..d33f0f5faf --- /dev/null +++ b/src/test/java/roomescape/service/FakeReservationTimeRepository.java @@ -0,0 +1,46 @@ +package roomescape.service; + +import java.time.LocalTime; +import java.util.ArrayList; +import java.util.List; +import java.util.NoSuchElementException; +import roomescape.model.ReservationTime; +import roomescape.repository.ReservationTimeRepository; + +class FakeReservationTimeRepository implements ReservationTimeRepository { + + private List reservationTimes = new ArrayList<>(List.of( + new ReservationTime(1, LocalTime.of(10, 0)), + new ReservationTime(2, LocalTime.of(11, 0)) + )); + + + @Override + public List findAllReservationTimes() { + return reservationTimes; + } + + @Override + public ReservationTime findReservationById(long id) { + return reservationTimes.stream() + .filter(reservationTime -> reservationTime.getId() == id) + .findFirst() + .orElseThrow(() -> new NoSuchElementException("해당하는 아이디가 없습니다.")); + } + + @Override + public ReservationTime addReservationTime(ReservationTime reservationTime) { + reservationTimes.add(reservationTime); + return new ReservationTime(3, reservationTime.getStartAt()); + } + + @Override + public void deleteReservationTime(long id) { + ReservationTime findReservationTime = reservationTimes.stream() + .filter(reservationTime -> reservationTime.getId() == id) + .findFirst() + .orElseThrow(() -> new NoSuchElementException("해당하는 아이디가 없습니다.")); + + reservationTimes.remove(findReservationTime); + } +} diff --git a/src/test/java/roomescape/service/ReservationServiceTest.java b/src/test/java/roomescape/service/ReservationServiceTest.java new file mode 100644 index 0000000000..d892b2ea5a --- /dev/null +++ b/src/test/java/roomescape/service/ReservationServiceTest.java @@ -0,0 +1,75 @@ +package roomescape.service; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.time.LocalDate; +import java.time.LocalTime; +import java.util.ArrayList; +import java.util.List; +import java.util.NoSuchElementException; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import roomescape.controller.request.ReservationRequest; +import roomescape.model.Reservation; +import roomescape.model.ReservationTime; +import roomescape.repository.ReservationRepository; + +class ReservationServiceTest { + ReservationService reservationService = new ReservationService(new FakeReservationRepository(), + new FakeReservationTimeRepository()); + + @DisplayName("모든 예약 시간을 반환한다") + @Test + void should_return_all_reservation_times() { + List reservations = reservationService.findAllReservations(); + assertThat(reservations).hasSize(2); + } + + @DisplayName("예약 시간을 추가한다") + @Test + void should_add_reservation_times() { + reservationService.addReservation( + new ReservationRequest(LocalDate.of(2024, 9, 1), "네오", 1)); + List allReservations = reservationService.findAllReservations(); + assertThat(allReservations).hasSize(3); + } + + @DisplayName("예약 시간을 삭제한다") + @Test + void should_remove_reservation_times() { + reservationService.deleteReservation(1); + List allReservations = reservationService.findAllReservations(); + assertThat(allReservations).hasSize(1); + } + + class FakeReservationRepository implements ReservationRepository { + + private List reservations = new ArrayList<>(List.of( + new Reservation(1, "브라운", LocalDate.of(2023, 8, 5), + new ReservationTime(1, LocalTime.of(10, 0))), + new Reservation(1, "리사", LocalDate.of(2023, 8, 1), + new ReservationTime(2, LocalTime.of(11, 0))))); + + @Override + public List getAllReservations() { + return reservations; + } + + @Override + public Reservation addReservation(Reservation reservation) { + reservations.add(reservation); + return reservation; + } + + @Override + public long deleteReservation(long id) { + Reservation foundReservation = reservations.stream() + .filter(reservation -> reservation.getId() == id) + .findFirst() + .orElseThrow(() -> new NoSuchElementException("아이디가 존재하지 않습니다.")); + reservations.remove(foundReservation); + return id; + } + } + +} diff --git a/src/test/java/roomescape/service/ReservationTimeServiceTest.java b/src/test/java/roomescape/service/ReservationTimeServiceTest.java new file mode 100644 index 0000000000..60cfa5d169 --- /dev/null +++ b/src/test/java/roomescape/service/ReservationTimeServiceTest.java @@ -0,0 +1,45 @@ +package roomescape.service; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.time.LocalTime; +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import roomescape.controller.request.ReservationTimeRequest; +import roomescape.model.ReservationTime; + +class ReservationTimeServiceTest { + ReservationTimeService reservationTimeService = new ReservationTimeService(new FakeReservationTimeRepository()); + + @DisplayName("모든 예약 시간을 반환한다") + @Test + void should_return_all_reservation_times() { + List reservationTimes = reservationTimeService.findAllReservationTimes(); + assertThat(reservationTimes).hasSize(2); + } + + @DisplayName("아이디에 해당하는 예약 시간을 반환한다.") + @Test + void should_get_reservation_time() { + ReservationTime reservationTime = reservationTimeService.findReservationTime(2); + assertThat(reservationTime.getStartAt()).isEqualTo(LocalTime.of(11, 0)); + } + + @DisplayName("예약 시간을 추가한다") + @Test + void should_add_reservation_times() { + ReservationTime reservationTime + = reservationTimeService.addReservationTime(new ReservationTimeRequest(LocalTime.of(10, 0))); + List allReservationTimes = reservationTimeService.findAllReservationTimes(); + assertThat(allReservationTimes).hasSize(3); + } + + @DisplayName("예약 시간을 삭제한다") + @Test + void should_remove_reservation_times() { + reservationTimeService.deleteReservationTime(1); + List allReservationTimes = reservationTimeService.findAllReservationTimes(); + assertThat(allReservationTimes).hasSize(1); + } +} From d0856b479a0d61afb1b5717cbcecd5cf455e85df Mon Sep 17 00:00:00 2001 From: SCY Date: Tue, 30 Apr 2024 15:47:49 +0900 Subject: [PATCH 02/74] =?UTF-8?q?chore(.gitignore):=20=EC=BB=A4=EB=B0=8B?= =?UTF-8?q?=EB=A9=94=EC=8B=9C=EC=A7=80=20=EC=84=A4=EC=A0=95=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: ehbeak --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index c2065bc262..5eac91a0d5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +.gitmessage.txt + HELP.md .gradle build/ From 53fa07e9d98927f72eaea90f6a148816d36f2faa Mon Sep 17 00:00:00 2001 From: SCY Date: Tue, 30 Apr 2024 15:48:39 +0900 Subject: [PATCH 03/74] =?UTF-8?q?test(RoomescapeApplicationTest):=20?= =?UTF-8?q?=ED=8F=AC=ED=8A=B8=20=EC=84=A4=EC=A0=95=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: ehbeak --- src/test/java/roomescape/RoomescapeApplicationTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/roomescape/RoomescapeApplicationTest.java b/src/test/java/roomescape/RoomescapeApplicationTest.java index 326a3ff677..59dbee2a1f 100644 --- a/src/test/java/roomescape/RoomescapeApplicationTest.java +++ b/src/test/java/roomescape/RoomescapeApplicationTest.java @@ -3,7 +3,7 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -@SpringBootTest +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) class RoomescapeApplicationTest { @Test From bd337ebb15cb86c23caf8d7d0313baa951a5d559 Mon Sep 17 00:00:00 2001 From: SCY Date: Tue, 30 Apr 2024 15:48:49 +0900 Subject: [PATCH 04/74] =?UTF-8?q?docs(README):=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=9A=94=EA=B5=AC=EC=82=AC=ED=95=AD=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: ehbeak --- README.md | 107 ++++++------------------------------------------------ 1 file changed, 12 insertions(+), 95 deletions(-) diff --git a/README.md b/README.md index 4a57877f84..638ff8883d 100644 --- a/README.md +++ b/README.md @@ -1,95 +1,12 @@ - -# 요구 사항 -### API 구현하기 -- [x] `localhost:8080/admin` get 요청 시 어드민 메인 페이지가 응답할 수 있다. -- [x] `localhost:8080` get 요청 시 어드민 메인 페이지가 응답할 수 있다. -- [x] `/admin/reservation` get 요청 시 예약 관리 페이지가 응답할 수 있다. -- [x] 예약 관리 페이지 응답 시, 현재 예약 목록을 함께 보여준다. -- [x] `/reservations` get 요청시 예약 목록을 조회한다. - - [x] 저장된 예약을 조회할 때 데이터베이스에 있는 값을 조회한다. -- [x] `/admin/reservation` post 요청 시 예약을 추가한다. - - [x] 예약을 추가할 때 데이터베이스에 값을 추가한다. -- [x] `/reservations/{id}` delete 요청 시 예약을 삭제한다. - - [x] id 값이 없는 경우 예외를 발생시킨다. - - [x] 예약을 삭제할 때 데이터베이스에 값을 삭제한다. -- [x] `/times` post 요청 시 시간을 추가한다. -- [x] `/times` get 요청 시 모든 시간을 조회한다. -- [x] `/times/{id}` delete 요청 시 해당 시간을 삭제한다. - -### 데이터베이스 -- [x] h2 데이터베이스와 연동한다. - - [x] gradle 의존성 추가한다. - - [x] 테이블 생성을 위한 스키마 정의한다. - - [x] h2 데이터베이스 콘솔 기능 활성화한다. - -### 콘솔 UI 지원 -- [x] 시간, 예약 관리 기능을 콘솔에서도 사용할 수 있도록 콘솔 UI를 추가합니다. -- [x] 콘솔 UI를 사용해 생성되는 데이터는 데이터베이스가 아닌 메모리에 저장합니다. - -``` -방탈출 관리 시스템 기능입니다. -1 방탈출 예약 조회 -2 방탈출 예약시간 조회 -3 방탈출 예약 추가 -4 방탈출 예약시간 추가 -5 방탈출 예약 삭제 -6 방탈출 예약시간 삭제 -7 종료 - -이용하실 기능의 번호를 입력해주세요 : 1 -방탈출 예약 내역입니다. -예약번호 예약자 날짜 시간 -1 파랑 2024-4-12 10:00:00 -2 배키 2024-4-13 11:00:00 -2 네오 2024-4-13 16:30:00 - - -이용하실 기능의 번호를 입력해주세요 : 2 -방탈출 시간 내역입니다. -순서 시간 -1 10:00:00 -2 11:00:00 - - -이용하실 기능의 번호를 입력해주세요 : 3 -방탈출 예약 화면입니다. -현재 방탈출 시간 내역입니다. -순서 시간 -1 10:00:00 -2 11:00:00 -원하는 시간에 맞는 순서를 입력해주세요 : 1 -예약자 이름을 입력해주세요 : 배키 -날짜를 입력해주세요. (ex. 2024-4-14) : 2024-5-12 -예약되었습니다. - - -이용하실 기능의 번호를 입력해주세요 : 4 -방탈출 예약시간 추가 화면입니다. -추가할 예약시간을 입력해주세요 (ex. 11:00:00) : 13:10:00 -예약시간이 추가되었습니다. - - -이용하실 기능의 번호를 입력해주세요 : 5 -방탈출 삭제 화면입니다. -현재 방탈출 예약 내역입니다. -예약번호 예약자 날짜 시간 -1 파랑 2024-4-12 10:00:00 -2 배키 2024-4-13 11:00:00 -3 네오 2024-4-13 16:30:00 -삭제하고 싶은 방탈출 예약번호를 입력해주세요 : 2 -방탈출 예약이 삭제되었습니다. - - -이용하실 기능의 번호를 입력해주세요 : 6 -방탈출 예약시간 삭제 화면입니다. -현재 방탈출 시간 내역입니다. -순서 시간 -1 10:00:00 -2 11:00:00 -삭제하고 싶은 예약시간의 순서를 입력해주세요 : 2 -예약시간이 삭제되었습니다. - - -이용하실 기능의 번호를 입력해주세요 : 5 -방탈출 예약관리 기능이 종료되었습니다. -``` +## 기능 요구사항 +- [ ] 예외 처리 + - [ ] 시간 생성 시 시작 시간에 유효하지 않은 값이 입력되었을 때 + - null, "", HH:mm이 아닌 경우 + - [ ] 예약 생성 시 예약자명, 날짜, 시간에 유효하지 않은 값이 입력 되었을 때 + - 예약자명: null, "" + - 날짜: null, "", yyyy-MM-dd이 아닌 경우 + - 시간: null, "", HH:mm이 아닌 경우 + - [ ] 특정 시간에 대한 예약이 존재하는데, 그 시간을 삭제하려 할 때 + - [ ] 존재하지 않는 id를 가진 데이터에 접근하려 할 때 + - [ ] 지나간 날짜와 시간에 대한 예약 생성 불가능 + - [ ] 중복 예약 불가능 From c03385801e1a3dd2176265cf630697c9792a7289 Mon Sep 17 00:00:00 2001 From: SCY Date: Tue, 30 Apr 2024 16:35:32 +0900 Subject: [PATCH 05/74] =?UTF-8?q?feat(reservationTime):=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20=EC=8B=9C=20=EC=98=88=EC=95=BD=20=EC=8B=9C=EA=B0=84?= =?UTF-8?q?=EC=9D=B4=20=EC=A1=B4=EC=9E=AC=ED=95=98=EC=A7=80=20=EC=95=8A?= =?UTF-8?q?=EB=8A=94=20=EA=B2=BD=EC=9A=B0=20=EC=98=88=EC=99=B8=20=EB=B0=9C?= =?UTF-8?q?=EC=83=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: ehbeak --- .../exception/NotFoundException.java | 8 +++++++ .../repository/ReservationTimeDAO.java | 7 ++++++ .../repository/ReservationTimeRepository.java | 2 ++ .../service/ReservationTimeService.java | 5 +++++ .../repository/ReservationTimeDAOTest.java | 15 +++++++++++++ .../FakeReservationTimeRepository.java | 8 ++++++- .../service/ReservationTimeServiceTest.java | 22 +++++++++++++++++-- 7 files changed, 64 insertions(+), 3 deletions(-) create mode 100644 src/main/java/roomescape/exception/NotFoundException.java diff --git a/src/main/java/roomescape/exception/NotFoundException.java b/src/main/java/roomescape/exception/NotFoundException.java new file mode 100644 index 0000000000..3edecf32e3 --- /dev/null +++ b/src/main/java/roomescape/exception/NotFoundException.java @@ -0,0 +1,8 @@ +package roomescape.exception; + +public class NotFoundException extends RuntimeException { + + public NotFoundException(String message) { + super(message); + } +} diff --git a/src/main/java/roomescape/repository/ReservationTimeDAO.java b/src/main/java/roomescape/repository/ReservationTimeDAO.java index 33797870d5..3fa925261a 100644 --- a/src/main/java/roomescape/repository/ReservationTimeDAO.java +++ b/src/main/java/roomescape/repository/ReservationTimeDAO.java @@ -57,4 +57,11 @@ public void deleteReservationTime(long id) { jdbcTemplate.update(sql, id); } + + @Override + public Long countReservationTimeById(long id) { + String sql = "select count(id) from reservation_time where id = ?"; + return jdbcTemplate.queryForObject(sql, (resultSet, ignored) -> + resultSet.getLong(1), id); + } } diff --git a/src/main/java/roomescape/repository/ReservationTimeRepository.java b/src/main/java/roomescape/repository/ReservationTimeRepository.java index 6eb2070c69..0847352c34 100644 --- a/src/main/java/roomescape/repository/ReservationTimeRepository.java +++ b/src/main/java/roomescape/repository/ReservationTimeRepository.java @@ -11,4 +11,6 @@ public interface ReservationTimeRepository { ReservationTime addReservationTime(ReservationTime reservationTime); void deleteReservationTime(long id); + + Long countReservationTimeById(long id); } diff --git a/src/main/java/roomescape/service/ReservationTimeService.java b/src/main/java/roomescape/service/ReservationTimeService.java index 56341dd74a..b99286b4e8 100644 --- a/src/main/java/roomescape/service/ReservationTimeService.java +++ b/src/main/java/roomescape/service/ReservationTimeService.java @@ -3,6 +3,7 @@ import java.util.List; import org.springframework.stereotype.Service; import roomescape.controller.request.ReservationTimeRequest; +import roomescape.exception.NotFoundException; import roomescape.model.ReservationTime; import roomescape.repository.ReservationTimeRepository; @@ -29,6 +30,10 @@ public ReservationTime findReservationTime(long id) { } public void deleteReservationTime(long id) { + Long count = reservationTimeRepository.countReservationTimeById(id); + if (count == null || count <= 0) { + throw new NotFoundException("[ERROR] 존재하지 않는 시간입니다."); + } reservationTimeRepository.deleteReservationTime(id); } } diff --git a/src/test/java/roomescape/repository/ReservationTimeDAOTest.java b/src/test/java/roomescape/repository/ReservationTimeDAOTest.java index 9b561d9964..5e25e70ad5 100644 --- a/src/test/java/roomescape/repository/ReservationTimeDAOTest.java +++ b/src/test/java/roomescape/repository/ReservationTimeDAOTest.java @@ -7,6 +7,7 @@ import java.util.List; import java.util.Map; import javax.sql.DataSource; + import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -80,4 +81,18 @@ void should_get_reservation_time() { ReservationTime reservationTime = reservationTimeDAOImpl.findReservationById(1); assertThat(reservationTime.getStartAt()).isEqualTo(LocalTime.of(10, 0)); } + + @DisplayName("아이디가 존재하면 참을 반환한다.") + @Test + void should_return_true_when_id_exist() { + long count = reservationTimeDAOImpl.countReservationTimeById(1); + assertThat(count).isEqualTo(1); + } + + @DisplayName("아이디가 존재하면 거짓을 반환한다.") + @Test + void should_return_false_when_id_not_exist() { + long count = reservationTimeDAOImpl.countReservationTimeById(100000000); + assertThat(count).isEqualTo(0); + } } diff --git a/src/test/java/roomescape/service/FakeReservationTimeRepository.java b/src/test/java/roomescape/service/FakeReservationTimeRepository.java index d33f0f5faf..182a73e65e 100644 --- a/src/test/java/roomescape/service/FakeReservationTimeRepository.java +++ b/src/test/java/roomescape/service/FakeReservationTimeRepository.java @@ -14,7 +14,6 @@ class FakeReservationTimeRepository implements ReservationTimeRepository { new ReservationTime(2, LocalTime.of(11, 0)) )); - @Override public List findAllReservationTimes() { return reservationTimes; @@ -43,4 +42,11 @@ public void deleteReservationTime(long id) { reservationTimes.remove(findReservationTime); } + + @Override + public Long countReservationTimeById(long id) { + return reservationTimes.stream() + .filter(reservationTime -> reservationTime.getId() == id) + .count(); + } } diff --git a/src/test/java/roomescape/service/ReservationTimeServiceTest.java b/src/test/java/roomescape/service/ReservationTimeServiceTest.java index 60cfa5d169..d01213613c 100644 --- a/src/test/java/roomescape/service/ReservationTimeServiceTest.java +++ b/src/test/java/roomescape/service/ReservationTimeServiceTest.java @@ -1,14 +1,17 @@ package roomescape.service; -import static org.assertj.core.api.Assertions.assertThat; - import java.time.LocalTime; import java.util.List; + +import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import roomescape.controller.request.ReservationTimeRequest; +import roomescape.exception.NotFoundException; import roomescape.model.ReservationTime; +import static org.assertj.core.api.Assertions.*; + class ReservationTimeServiceTest { ReservationTimeService reservationTimeService = new ReservationTimeService(new FakeReservationTimeRepository()); @@ -42,4 +45,19 @@ void should_remove_reservation_times() { List allReservationTimes = reservationTimeService.findAllReservationTimes(); assertThat(allReservationTimes).hasSize(1); } + + @DisplayName("존재하지 않는 시간이면 예외를 발생시킨다.") + @Test + void should_throw_exception_when_not_exist_id() { + assertThatThrownBy(() -> reservationTimeService.deleteReservationTime(10000000)) + .isInstanceOf(NotFoundException.class) + .hasMessage("[ERROR] 존재하지 않는 시간입니다."); + } + + @DisplayName("존재하는 시간이면 예외가 발생하지 않는다.") + @Test + void should_not_throw_exception_when_exist_id() { + assertThatCode(() -> reservationTimeService.deleteReservationTime(1)) + .doesNotThrowAnyException(); + } } From b2b611cd9b71ced9f9f6e4f09900e0a035285dc5 Mon Sep 17 00:00:00 2001 From: SCY Date: Tue, 30 Apr 2024 16:53:57 +0900 Subject: [PATCH 06/74] =?UTF-8?q?feat(reservation):=20=EC=82=AD=EC=A0=9C?= =?UTF-8?q?=20=EC=8B=9C=20=EC=98=88=EC=95=BD=EC=9D=B4=20=EC=A1=B4=EC=9E=AC?= =?UTF-8?q?=ED=95=98=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EA=B2=BD=EC=9A=B0=20?= =?UTF-8?q?=EC=98=88=EC=99=B8=20=EB=B0=9C=EC=83=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: ehbeak --- .../roomescape/repository/ReservationDAO.java | 6 ++++ .../repository/ReservationRepository.java | 2 ++ .../service/ReservationService.java | 5 ++++ .../repository/ReservationDAOTest.java | 14 +++++++++ .../service/ReservationServiceTest.java | 30 +++++++++++++++++-- 5 files changed, 54 insertions(+), 3 deletions(-) diff --git a/src/main/java/roomescape/repository/ReservationDAO.java b/src/main/java/roomescape/repository/ReservationDAO.java index c4f20dbac3..feb344b6a0 100644 --- a/src/main/java/roomescape/repository/ReservationDAO.java +++ b/src/main/java/roomescape/repository/ReservationDAO.java @@ -64,4 +64,10 @@ public long deleteReservation(long id) { String sql = "delete from reservation where id = ?"; return jdbcTemplate.update(sql, id); } + + @Override + public Long countReservationById(long id) { + String sql = "select count(id) from reservation where id = ?"; + return jdbcTemplate.queryForObject(sql, (resultSet, ignored) -> resultSet.getLong(1), id); + } } diff --git a/src/main/java/roomescape/repository/ReservationRepository.java b/src/main/java/roomescape/repository/ReservationRepository.java index c09e2bee1c..6c8d1bb6d2 100644 --- a/src/main/java/roomescape/repository/ReservationRepository.java +++ b/src/main/java/roomescape/repository/ReservationRepository.java @@ -9,4 +9,6 @@ public interface ReservationRepository { Reservation addReservation(Reservation reservation); long deleteReservation(long id); + + Long countReservationById(long id); } diff --git a/src/main/java/roomescape/service/ReservationService.java b/src/main/java/roomescape/service/ReservationService.java index 2b8dc29ecf..44ba0d3059 100644 --- a/src/main/java/roomescape/service/ReservationService.java +++ b/src/main/java/roomescape/service/ReservationService.java @@ -3,6 +3,7 @@ import java.util.List; import org.springframework.stereotype.Service; import roomescape.controller.request.ReservationRequest; +import roomescape.exception.NotFoundException; import roomescape.model.Reservation; import roomescape.model.ReservationTime; import roomescape.repository.ReservationRepository; @@ -30,6 +31,10 @@ public Reservation addReservation(ReservationRequest request) { } public void deleteReservation(long id) { + Long count = reservationRepository.countReservationById(id); + if (count == null || count <= 0) { + throw new NotFoundException("[ERROR] 존재하지 않는 예약입니다."); + } reservationRepository.deleteReservation(id); } } diff --git a/src/test/java/roomescape/repository/ReservationDAOTest.java b/src/test/java/roomescape/repository/ReservationDAOTest.java index fbd97a4334..a7336e66f2 100644 --- a/src/test/java/roomescape/repository/ReservationDAOTest.java +++ b/src/test/java/roomescape/repository/ReservationDAOTest.java @@ -102,4 +102,18 @@ void should_delete_reservation() { Integer count = jdbcTemplate.queryForObject("select count(1) from reservation", Integer.class); assertThat(count).isEqualTo(1); } + + @DisplayName("아이디가 존재하면 참을 반환한다.") + @Test + void should_return_true_when_id_exist() { + long count = reservationRepository.countReservationById(1); + assertThat(count).isEqualTo(1); + } + + @DisplayName("아이디가 존재하면 거짓을 반환한다.") + @Test + void should_return_false_when_id_not_exist() { + long count = reservationRepository.countReservationById(100000000); + assertThat(count).isEqualTo(0); + } } diff --git a/src/test/java/roomescape/service/ReservationServiceTest.java b/src/test/java/roomescape/service/ReservationServiceTest.java index d892b2ea5a..6add68041e 100644 --- a/src/test/java/roomescape/service/ReservationServiceTest.java +++ b/src/test/java/roomescape/service/ReservationServiceTest.java @@ -1,19 +1,22 @@ package roomescape.service; -import static org.assertj.core.api.Assertions.assertThat; - import java.time.LocalDate; import java.time.LocalTime; import java.util.ArrayList; import java.util.List; import java.util.NoSuchElementException; + +import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import roomescape.controller.request.ReservationRequest; +import roomescape.exception.NotFoundException; import roomescape.model.Reservation; import roomescape.model.ReservationTime; import roomescape.repository.ReservationRepository; +import static org.assertj.core.api.Assertions.*; + class ReservationServiceTest { ReservationService reservationService = new ReservationService(new FakeReservationRepository(), new FakeReservationTimeRepository()); @@ -42,6 +45,21 @@ void should_remove_reservation_times() { assertThat(allReservations).hasSize(1); } + @DisplayName("존재하지 않는 예약을 삭제하면 예외가 발생한다.") + @Test + void should_throw_exception_when_not_exist_reservation_time() { + assertThatThrownBy(() -> reservationService.deleteReservation(100000000)) + .isInstanceOf(NotFoundException.class) + .hasMessage("[ERROR] 존재하지 않는 예약입니다."); + } + + @DisplayName("존재하는 예약을 삭제하면 예외가 발생하지 않는다.") + @Test + void should_not_throw_exception_when_exist_reservation_time() { + assertThatCode(() -> reservationService.deleteReservation(1)) + .doesNotThrowAnyException(); + } + class FakeReservationRepository implements ReservationRepository { private List reservations = new ArrayList<>(List.of( @@ -70,6 +88,12 @@ public long deleteReservation(long id) { reservations.remove(foundReservation); return id; } - } + @Override + public Long countReservationById(long id) { + return reservations.stream() + .filter(reservation -> reservation.getId() == id) + .count(); + } + } } From b8f203eadc594d7158c67a79a7b47e39fb06e206 Mon Sep 17 00:00:00 2001 From: SCY Date: Tue, 30 Apr 2024 17:42:43 +0900 Subject: [PATCH 07/74] =?UTF-8?q?feat(ReservationTimeRequest):=20=EC=8B=9C?= =?UTF-8?q?=EA=B0=84=20=EC=83=9D=EC=84=B1=20=EC=8B=9C=20=EC=9C=A0=ED=9A=A8?= =?UTF-8?q?=ED=95=98=EC=A7=80=20=EC=95=8A=EC=9D=80=20=EA=B0=92=20=EC=98=88?= =?UTF-8?q?=EC=99=B8=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: ehbeak --- README.md | 4 +- .../request/ReservationTimeRequest.java | 26 ++++++++++- .../exception/BadRequestException.java | 7 +++ .../service/ReservationTimeService.java | 2 +- .../ReservationTimeControllerTest.java | 2 +- .../request/ReservationRequestTest.java | 17 +++++++ .../request/ReservationTimeRequestTest.java | 46 +++++++++++++++++++ .../service/ReservationTimeServiceTest.java | 2 +- 8 files changed, 100 insertions(+), 6 deletions(-) create mode 100644 src/main/java/roomescape/exception/BadRequestException.java create mode 100644 src/test/java/roomescape/controller/request/ReservationRequestTest.java create mode 100644 src/test/java/roomescape/controller/request/ReservationTimeRequestTest.java diff --git a/README.md b/README.md index 638ff8883d..1327bfe61d 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ ## 기능 요구사항 - [ ] 예외 처리 - - [ ] 시간 생성 시 시작 시간에 유효하지 않은 값이 입력되었을 때 + - [x] 시간 생성 시 시작 시간에 유효하지 않은 값이 입력되었을 때 - null, "", HH:mm이 아닌 경우 - [ ] 예약 생성 시 예약자명, 날짜, 시간에 유효하지 않은 값이 입력 되었을 때 - 예약자명: null, "" - 날짜: null, "", yyyy-MM-dd이 아닌 경우 - 시간: null, "", HH:mm이 아닌 경우 - [ ] 특정 시간에 대한 예약이 존재하는데, 그 시간을 삭제하려 할 때 - - [ ] 존재하지 않는 id를 가진 데이터에 접근하려 할 때 + - [x] 존재하지 않는 id를 가진 데이터에 접근하려 할 때 - [ ] 지나간 날짜와 시간에 대한 예약 생성 불가능 - [ ] 중복 예약 불가능 diff --git a/src/main/java/roomescape/controller/request/ReservationTimeRequest.java b/src/main/java/roomescape/controller/request/ReservationTimeRequest.java index 6981d408af..f0d1c729b0 100644 --- a/src/main/java/roomescape/controller/request/ReservationTimeRequest.java +++ b/src/main/java/roomescape/controller/request/ReservationTimeRequest.java @@ -1,6 +1,30 @@ package roomescape.controller.request; +import roomescape.exception.BadRequestException; + import java.time.LocalTime; +import java.time.format.DateTimeParseException; + +public class ReservationTimeRequest { + + private final LocalTime startAt; + + public ReservationTimeRequest(String startAt) { + validate(startAt); + try { + this.startAt = LocalTime.parse(startAt); + } catch (DateTimeParseException exception) { + throw new BadRequestException("[ERROR] 유효하지 않은 요청입니다."); + } + } + + private void validate(String startAt) { + if (startAt == null || startAt.isEmpty()) { + throw new BadRequestException("[ERROR] 유효하지 않은 요청입니다."); + } + } -public record ReservationTimeRequest(LocalTime startAt) { + public LocalTime getStartAt() { + return startAt; + } } diff --git a/src/main/java/roomescape/exception/BadRequestException.java b/src/main/java/roomescape/exception/BadRequestException.java new file mode 100644 index 0000000000..e614e2d796 --- /dev/null +++ b/src/main/java/roomescape/exception/BadRequestException.java @@ -0,0 +1,7 @@ +package roomescape.exception; + +public class BadRequestException extends RuntimeException { + public BadRequestException(String message) { + super(message); + } +} diff --git a/src/main/java/roomescape/service/ReservationTimeService.java b/src/main/java/roomescape/service/ReservationTimeService.java index b99286b4e8..cc453edb3a 100644 --- a/src/main/java/roomescape/service/ReservationTimeService.java +++ b/src/main/java/roomescape/service/ReservationTimeService.java @@ -21,7 +21,7 @@ public List findAllReservationTimes() { } public ReservationTime addReservationTime(ReservationTimeRequest request) { - ReservationTime reservationTime = new ReservationTime(request.startAt()); + ReservationTime reservationTime = new ReservationTime(request.getStartAt()); return reservationTimeRepository.addReservationTime(reservationTime); } diff --git a/src/test/java/roomescape/controller/ReservationTimeControllerTest.java b/src/test/java/roomescape/controller/ReservationTimeControllerTest.java index 9b465fe612..8923385e9d 100644 --- a/src/test/java/roomescape/controller/ReservationTimeControllerTest.java +++ b/src/test/java/roomescape/controller/ReservationTimeControllerTest.java @@ -42,7 +42,7 @@ void should_get_reservation_times() { @DisplayName("예약 시간을 추가한다") @Test void should_add_reservation_times() { - ReservationTimeRequest request = new ReservationTimeRequest(LocalTime.of(10, 0)); + ReservationTimeRequest request = new ReservationTimeRequest("10:00"); RestAssured.given().log().all() .contentType(ContentType.JSON) diff --git a/src/test/java/roomescape/controller/request/ReservationRequestTest.java b/src/test/java/roomescape/controller/request/ReservationRequestTest.java new file mode 100644 index 0000000000..4c6b00fc77 --- /dev/null +++ b/src/test/java/roomescape/controller/request/ReservationRequestTest.java @@ -0,0 +1,17 @@ +package roomescape.controller.request; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import roomescape.exception.BadRequestException; + +class ReservationRequestTest { + + @DisplayName("시간이 null인 경우 예외를 발생시킨다.") + @Test + void should_throw_exception_when_startAt_is_null() { + Assertions.assertThatThrownBy(() -> new ReservationTimeRequest(null)) + .isInstanceOf(BadRequestException.class) + .hasMessage("[ERROR] 유효하지 않은 요청입니다."); + } +} \ No newline at end of file diff --git a/src/test/java/roomescape/controller/request/ReservationTimeRequestTest.java b/src/test/java/roomescape/controller/request/ReservationTimeRequestTest.java new file mode 100644 index 0000000000..d4da2bc089 --- /dev/null +++ b/src/test/java/roomescape/controller/request/ReservationTimeRequestTest.java @@ -0,0 +1,46 @@ +package roomescape.controller.request; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import roomescape.exception.BadRequestException; + +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class ReservationTimeRequestTest { + + @DisplayName("시간이 null인 경우 예외를 발생시킨다.") + @Test + void should_throw_exception_when_startAt_is_null() { + assertThatThrownBy(() -> new ReservationTimeRequest(null)) + .isInstanceOf(BadRequestException.class) + .hasMessage("[ERROR] 유효하지 않은 요청입니다."); + } + + @DisplayName("시간이 비어있는 경우 예외를 발생시킨다.") + @Test + void should_throw_exception_when_startAt_is_empty() { + assertThatThrownBy(() -> new ReservationTimeRequest("")) + .isInstanceOf(BadRequestException.class) + .hasMessage("[ERROR] 유효하지 않은 요청입니다."); + } + + @DisplayName("시간의 형식이 지켜지지 않은 경우 예외를 발생시킨다.") + @ParameterizedTest + @ValueSource(strings = {"10-00", "25:12", "12:00:00:01"}) + void should_throw_exception_when_startAt_is_bad_format(String startAt) { + assertThatThrownBy(() -> new ReservationTimeRequest(startAt)) + .isInstanceOf(BadRequestException.class) + .hasMessage("[ERROR] 유효하지 않은 요청입니다."); + } + + @DisplayName("유효한 시간이면 예외가 발생하지 않는다.") + @ParameterizedTest + @ValueSource(strings = {"10:00", "23:59:59", "12:00:00", "00:00:00"}) + void should_not_throw_exception_when_startAt_is_good_format(String startAt) { + assertThatCode(() -> new ReservationTimeRequest(startAt)) + .doesNotThrowAnyException(); + } +} diff --git a/src/test/java/roomescape/service/ReservationTimeServiceTest.java b/src/test/java/roomescape/service/ReservationTimeServiceTest.java index d01213613c..0de6ba6906 100644 --- a/src/test/java/roomescape/service/ReservationTimeServiceTest.java +++ b/src/test/java/roomescape/service/ReservationTimeServiceTest.java @@ -33,7 +33,7 @@ void should_get_reservation_time() { @Test void should_add_reservation_times() { ReservationTime reservationTime - = reservationTimeService.addReservationTime(new ReservationTimeRequest(LocalTime.of(10, 0))); + = reservationTimeService.addReservationTime(new ReservationTimeRequest("10:00")); List allReservationTimes = reservationTimeService.findAllReservationTimes(); assertThat(allReservationTimes).hasSize(3); } From b570b61acc836e2af03d08f407805e3c9a3ac220 Mon Sep 17 00:00:00 2001 From: SCY Date: Tue, 30 Apr 2024 17:49:27 +0900 Subject: [PATCH 08/74] =?UTF-8?q?feat(ReservationRequest):=20=EC=98=88?= =?UTF-8?q?=EC=95=BD=20=EC=83=9D=EC=84=B1=20=EC=8B=9C=20=EC=9C=A0=ED=9A=A8?= =?UTF-8?q?=ED=95=98=EC=A7=80=20=EC=95=8A=EC=9D=80=20=EC=98=88=EC=95=BD?= =?UTF-8?q?=EC=9E=90=EB=AA=85=20=EC=98=88=EC=99=B8=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: ehbeak --- .../request/ReservationRequest.java | 33 ++++++++++++++++++- .../service/ReservationService.java | 4 +-- .../request/ReservationRequestTest.java | 19 ++++++++--- 3 files changed, 49 insertions(+), 7 deletions(-) diff --git a/src/main/java/roomescape/controller/request/ReservationRequest.java b/src/main/java/roomescape/controller/request/ReservationRequest.java index 76e15acd02..481f74ce93 100644 --- a/src/main/java/roomescape/controller/request/ReservationRequest.java +++ b/src/main/java/roomescape/controller/request/ReservationRequest.java @@ -1,6 +1,37 @@ package roomescape.controller.request; +import roomescape.exception.BadRequestException; + import java.time.LocalDate; -public record ReservationRequest(LocalDate date, String name, long timeId) { +public class ReservationRequest { + + private final LocalDate date; + private final String name; + private final long timeId; + + public ReservationRequest(LocalDate date, String name, long timeId) { + validateName(name); + this.date = date; + this.name = name; + this.timeId = timeId; + } + + private void validateName(String name) { + if (name == null || name.isEmpty()) { + throw new BadRequestException("[ERROR] 유효하지 않은 요청입니다."); + } + } + + public LocalDate getDate() { + return date; + } + + public String getName() { + return name; + } + + public long getTimeId() { + return timeId; + } } diff --git a/src/main/java/roomescape/service/ReservationService.java b/src/main/java/roomescape/service/ReservationService.java index 44ba0d3059..7caf983097 100644 --- a/src/main/java/roomescape/service/ReservationService.java +++ b/src/main/java/roomescape/service/ReservationService.java @@ -26,8 +26,8 @@ public List findAllReservations() { } public Reservation addReservation(ReservationRequest request) { - ReservationTime reservationTime = reservationTimeDAO.findReservationById(request.timeId()); - return reservationRepository.addReservation(new Reservation(request.name(), request.date(), reservationTime)); + ReservationTime reservationTime = reservationTimeDAO.findReservationById(request.getTimeId()); + return reservationRepository.addReservation(new Reservation(request.getName(), request.getDate(), reservationTime)); } public void deleteReservation(long id) { diff --git a/src/test/java/roomescape/controller/request/ReservationRequestTest.java b/src/test/java/roomescape/controller/request/ReservationRequestTest.java index 4c6b00fc77..1b920d82af 100644 --- a/src/test/java/roomescape/controller/request/ReservationRequestTest.java +++ b/src/test/java/roomescape/controller/request/ReservationRequestTest.java @@ -1,17 +1,28 @@ package roomescape.controller.request; -import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import roomescape.exception.BadRequestException; +import java.time.LocalDate; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + class ReservationRequestTest { - @DisplayName("시간이 null인 경우 예외를 발생시킨다.") + @DisplayName("예약자명이 null인 경우 예외를 발생시킨다.") @Test void should_throw_exception_when_startAt_is_null() { - Assertions.assertThatThrownBy(() -> new ReservationTimeRequest(null)) + assertThatThrownBy(() -> new ReservationRequest(LocalDate.of(2024, 4, 30), null, 1)) + .isInstanceOf(BadRequestException.class) + .hasMessage("[ERROR] 유효하지 않은 요청입니다."); + } + + @DisplayName("예약자명이 빈 문자열인 경우 예외를 발생시킨다.") + @Test + void should_throw_exception_when_startAt_is_empty() { + assertThatThrownBy(() -> new ReservationRequest(LocalDate.of(2024, 4, 30), "", 1)) .isInstanceOf(BadRequestException.class) .hasMessage("[ERROR] 유효하지 않은 요청입니다."); } -} \ No newline at end of file +} From f5161b915f185fc38e8b6551efa2a6469a9c65e2 Mon Sep 17 00:00:00 2001 From: SCY Date: Wed, 1 May 2024 13:10:04 +0900 Subject: [PATCH 09/74] =?UTF-8?q?feat(ReservationRequest):=20=EC=98=88?= =?UTF-8?q?=EC=95=BD=20=EC=83=9D=EC=84=B1=20=EC=8B=9C=20=EC=9C=A0=ED=9A=A8?= =?UTF-8?q?=ED=95=98=EC=A7=80=20=EC=95=8A=EC=9D=80=20=EB=82=A0=EC=A7=9C=20?= =?UTF-8?q?=EC=98=88=EC=99=B8=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: ehbeak --- README.md | 2 +- .../request/ReservationRequest.java | 25 ++++++-- .../request/ReservationTimeRequest.java | 5 +- .../controller/ReservationControllerTest.java | 2 +- .../request/ReservationRequestTest.java | 60 +++++++++++++++---- .../service/ReservationServiceTest.java | 2 +- 6 files changed, 75 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 1327bfe61d..3b0d13421a 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ - [ ] 예외 처리 - [x] 시간 생성 시 시작 시간에 유효하지 않은 값이 입력되었을 때 - null, "", HH:mm이 아닌 경우 - - [ ] 예약 생성 시 예약자명, 날짜, 시간에 유효하지 않은 값이 입력 되었을 때 + - [x] 예약 생성 시 예약자명, 날짜, 시간에 유효하지 않은 값이 입력 되었을 때 - 예약자명: null, "" - 날짜: null, "", yyyy-MM-dd이 아닌 경우 - 시간: null, "", HH:mm이 아닌 경우 diff --git a/src/main/java/roomescape/controller/request/ReservationRequest.java b/src/main/java/roomescape/controller/request/ReservationRequest.java index 481f74ce93..225878bfaa 100644 --- a/src/main/java/roomescape/controller/request/ReservationRequest.java +++ b/src/main/java/roomescape/controller/request/ReservationRequest.java @@ -3,20 +3,35 @@ import roomescape.exception.BadRequestException; import java.time.LocalDate; +import java.time.format.DateTimeParseException; public class ReservationRequest { - private final LocalDate date; - private final String name; - private final long timeId; + private LocalDate date; + private String name; + private long timeId; - public ReservationRequest(LocalDate date, String name, long timeId) { + public ReservationRequest(String date, String name, long timeId) { validateName(name); - this.date = date; + validateDate(date); + try { + this.date = LocalDate.parse(date); + } catch (DateTimeParseException exception) { + throw new BadRequestException("[ERROR] 유효하지 않은 요청입니다."); + } this.name = name; this.timeId = timeId; } + private ReservationRequest() { + } + + private void validateDate(String date) { + if (date == null || date.isEmpty()) { + throw new BadRequestException("[ERROR] 유효하지 않은 요청입니다."); + } + } + private void validateName(String name) { if (name == null || name.isEmpty()) { throw new BadRequestException("[ERROR] 유효하지 않은 요청입니다."); diff --git a/src/main/java/roomescape/controller/request/ReservationTimeRequest.java b/src/main/java/roomescape/controller/request/ReservationTimeRequest.java index f0d1c729b0..704a001bc5 100644 --- a/src/main/java/roomescape/controller/request/ReservationTimeRequest.java +++ b/src/main/java/roomescape/controller/request/ReservationTimeRequest.java @@ -7,7 +7,7 @@ public class ReservationTimeRequest { - private final LocalTime startAt; + private LocalTime startAt; public ReservationTimeRequest(String startAt) { validate(startAt); @@ -18,6 +18,9 @@ public ReservationTimeRequest(String startAt) { } } + private ReservationTimeRequest() { + } + private void validate(String startAt) { if (startAt == null || startAt.isEmpty()) { throw new BadRequestException("[ERROR] 유효하지 않은 요청입니다."); diff --git a/src/test/java/roomescape/controller/ReservationControllerTest.java b/src/test/java/roomescape/controller/ReservationControllerTest.java index a78187653f..f174214435 100644 --- a/src/test/java/roomescape/controller/ReservationControllerTest.java +++ b/src/test/java/roomescape/controller/ReservationControllerTest.java @@ -50,7 +50,7 @@ void should_insert_reservation() { Integer count1 = jdbcTemplate.queryForObject("SELECT count(1) from reservation", Integer.class); System.out.println("count1 = " + count1); ReservationRequest request = new ReservationRequest( - LocalDate.of(2023, 8, 5), + "2023-08-05", "브라운", 1); diff --git a/src/test/java/roomescape/controller/request/ReservationRequestTest.java b/src/test/java/roomescape/controller/request/ReservationRequestTest.java index 1b920d82af..4d78c315fe 100644 --- a/src/test/java/roomescape/controller/request/ReservationRequestTest.java +++ b/src/test/java/roomescape/controller/request/ReservationRequestTest.java @@ -1,7 +1,10 @@ package roomescape.controller.request; import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; import roomescape.exception.BadRequestException; import java.time.LocalDate; @@ -10,19 +13,52 @@ class ReservationRequestTest { - @DisplayName("예약자명이 null인 경우 예외를 발생시킨다.") - @Test - void should_throw_exception_when_startAt_is_null() { - assertThatThrownBy(() -> new ReservationRequest(LocalDate.of(2024, 4, 30), null, 1)) - .isInstanceOf(BadRequestException.class) - .hasMessage("[ERROR] 유효하지 않은 요청입니다."); + @Nested + class ReservationRequestNameTest { + + @DisplayName("예약자명이 null인 경우 예외를 발생시킨다.") + @Test + void should_throw_exception_when_name_is_null() { + assertThatThrownBy(() -> new ReservationRequest("2024-04-30", null, 1)) + .isInstanceOf(BadRequestException.class) + .hasMessage("[ERROR] 유효하지 않은 요청입니다."); + } + + @DisplayName("예약자명이 빈 문자열인 경우 예외를 발생시킨다.") + @Test + void should_throw_exception_when_name_is_empty() { + assertThatThrownBy(() -> new ReservationRequest("2024-04-30", "", 1)) + .isInstanceOf(BadRequestException.class) + .hasMessage("[ERROR] 유효하지 않은 요청입니다."); + } } - @DisplayName("예약자명이 빈 문자열인 경우 예외를 발생시킨다.") - @Test - void should_throw_exception_when_startAt_is_empty() { - assertThatThrownBy(() -> new ReservationRequest(LocalDate.of(2024, 4, 30), "", 1)) - .isInstanceOf(BadRequestException.class) - .hasMessage("[ERROR] 유효하지 않은 요청입니다."); + @Nested + class ReservationRequestDateTest { + + @DisplayName("날짜가 null인 경우 예외를 발생시킨다.") + @Test + void should_throw_exception_when_date_is_null() { + assertThatThrownBy(() -> new ReservationRequest(null, "에버", 1)) + .isInstanceOf(BadRequestException.class) + .hasMessage("[ERROR] 유효하지 않은 요청입니다."); + } + + @DisplayName("날짜가 비어있는 경우 예외를 발생시킨다.") + @Test + void should_throw_exception_when_date_is_empty() { + assertThatThrownBy(() -> new ReservationRequest("", "배키", 1)) + .isInstanceOf(BadRequestException.class) + .hasMessage("[ERROR] 유효하지 않은 요청입니다."); + } + + @DisplayName("날짜의 형식이 유효하지 않은 경우 예외를 발생시킨다.") + @ParameterizedTest + @ValueSource(strings = {"2024:03:27", "2024/01/11", "에베", "12-12"}) + void should_throw_exception_when_date_is_bad_format(String date) { + assertThatThrownBy(() -> new ReservationRequest(date, "배키", 1)) + .isInstanceOf(BadRequestException.class) + .hasMessage("[ERROR] 유효하지 않은 요청입니다."); + } } } diff --git a/src/test/java/roomescape/service/ReservationServiceTest.java b/src/test/java/roomescape/service/ReservationServiceTest.java index 6add68041e..9798772fca 100644 --- a/src/test/java/roomescape/service/ReservationServiceTest.java +++ b/src/test/java/roomescape/service/ReservationServiceTest.java @@ -32,7 +32,7 @@ void should_return_all_reservation_times() { @Test void should_add_reservation_times() { reservationService.addReservation( - new ReservationRequest(LocalDate.of(2024, 9, 1), "네오", 1)); + new ReservationRequest("2020-01-01", "네오", 1)); List allReservations = reservationService.findAllReservations(); assertThat(allReservations).hasSize(3); } From 4c54b7e1606a28a5e017377ef295a7862ffb9b61 Mon Sep 17 00:00:00 2001 From: SCY Date: Wed, 1 May 2024 13:35:29 +0900 Subject: [PATCH 10/74] =?UTF-8?q?feat(ReservationService):=20=ED=98=84?= =?UTF-8?q?=EC=9E=AC=20=EC=9D=B4=EC=A0=84=20=EC=98=88=EC=95=BD=EC=97=90=20?= =?UTF-8?q?=EB=8C=80=ED=95=9C=20=EC=98=88=EC=99=B8=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: ehbeak --- README.md | 2 +- .../service/ReservationService.java | 8 +++++++ .../controller/ReservationControllerTest.java | 3 +-- .../service/ReservationServiceTest.java | 22 ++++++++++++++++++- 4 files changed, 31 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 3b0d13421a..630825cf79 100644 --- a/README.md +++ b/README.md @@ -8,5 +8,5 @@ - 시간: null, "", HH:mm이 아닌 경우 - [ ] 특정 시간에 대한 예약이 존재하는데, 그 시간을 삭제하려 할 때 - [x] 존재하지 않는 id를 가진 데이터에 접근하려 할 때 - - [ ] 지나간 날짜와 시간에 대한 예약 생성 불가능 + - [x] 지나간 날짜와 시간에 대한 예약 생성 불가능 - [ ] 중복 예약 불가능 diff --git a/src/main/java/roomescape/service/ReservationService.java b/src/main/java/roomescape/service/ReservationService.java index 7caf983097..05835adb0e 100644 --- a/src/main/java/roomescape/service/ReservationService.java +++ b/src/main/java/roomescape/service/ReservationService.java @@ -1,8 +1,12 @@ package roomescape.service; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; import java.util.List; import org.springframework.stereotype.Service; import roomescape.controller.request.ReservationRequest; +import roomescape.exception.BadRequestException; import roomescape.exception.NotFoundException; import roomescape.model.Reservation; import roomescape.model.ReservationTime; @@ -27,6 +31,10 @@ public List findAllReservations() { public Reservation addReservation(ReservationRequest request) { ReservationTime reservationTime = reservationTimeDAO.findReservationById(request.getTimeId()); + LocalDateTime reservationDateTime = LocalDateTime.of(request.getDate(), reservationTime.getStartAt()); + if (reservationDateTime.isBefore(LocalDateTime.now())) { + throw new BadRequestException("[ERROR] 현재 이전 예약은 할 수 없습니다."); + } return reservationRepository.addReservation(new Reservation(request.getName(), request.getDate(), reservationTime)); } diff --git a/src/test/java/roomescape/controller/ReservationControllerTest.java b/src/test/java/roomescape/controller/ReservationControllerTest.java index f174214435..243725140c 100644 --- a/src/test/java/roomescape/controller/ReservationControllerTest.java +++ b/src/test/java/roomescape/controller/ReservationControllerTest.java @@ -48,9 +48,8 @@ void should_get_reservations() { @Test void should_insert_reservation() { Integer count1 = jdbcTemplate.queryForObject("SELECT count(1) from reservation", Integer.class); - System.out.println("count1 = " + count1); ReservationRequest request = new ReservationRequest( - "2023-08-05", + "2030-08-05", "브라운", 1); diff --git a/src/test/java/roomescape/service/ReservationServiceTest.java b/src/test/java/roomescape/service/ReservationServiceTest.java index 9798772fca..5a2ae3fbf9 100644 --- a/src/test/java/roomescape/service/ReservationServiceTest.java +++ b/src/test/java/roomescape/service/ReservationServiceTest.java @@ -1,6 +1,7 @@ package roomescape.service; import java.time.LocalDate; +import java.time.LocalDateTime; import java.time.LocalTime; import java.util.ArrayList; import java.util.List; @@ -10,6 +11,7 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import roomescape.controller.request.ReservationRequest; +import roomescape.exception.BadRequestException; import roomescape.exception.NotFoundException; import roomescape.model.Reservation; import roomescape.model.ReservationTime; @@ -32,7 +34,7 @@ void should_return_all_reservation_times() { @Test void should_add_reservation_times() { reservationService.addReservation( - new ReservationRequest("2020-01-01", "네오", 1)); + new ReservationRequest("2030-01-01", "네오", 1)); List allReservations = reservationService.findAllReservations(); assertThat(allReservations).hasSize(3); } @@ -60,6 +62,24 @@ void should_not_throw_exception_when_exist_reservation_time() { .doesNotThrowAnyException(); } + //todo 현재 시간에 따라 테스트 깨짐 + 경계값 테스트 + @DisplayName("현재 이전으로 예약하면 예외가 발생한다.") + @Test + void should_throw_exception_when_previous_date() { + ReservationRequest request = new ReservationRequest("2000-01-11", "에버", 1); + assertThatThrownBy(() -> reservationService.addReservation(request)) + .isInstanceOf(BadRequestException.class) + .hasMessage("[ERROR] 현재 이전 예약은 할 수 없습니다."); + } + + @DisplayName("현재 이후로 예약하면 예외가 발생하지 않는다.") + @Test + void should_not_throw_exception_when_later_date() { + ReservationRequest request = new ReservationRequest("2030-01-11", "에버", 1); + assertThatCode(() -> reservationService.addReservation(request)) + .doesNotThrowAnyException(); + } + class FakeReservationRepository implements ReservationRepository { private List reservations = new ArrayList<>(List.of( From b87703da7cd0f9e3da70498b2d4dd52430bed276 Mon Sep 17 00:00:00 2001 From: SCY Date: Wed, 1 May 2024 14:03:29 +0900 Subject: [PATCH 11/74] =?UTF-8?q?feat(ReservationTimeService):=20=ED=8A=B9?= =?UTF-8?q?=EC=A0=95=20=EC=8B=9C=EA=B0=84=EC=97=90=20=EB=8C=80=ED=95=9C=20?= =?UTF-8?q?=EC=98=88=EC=95=BD=EC=9D=B4=20=EC=A1=B4=EC=9E=AC=ED=95=98?= =?UTF-8?q?=EB=8A=94=20=EA=B2=BD=EC=9A=B0,=20=EA=B7=B8=20=EC=8B=9C?= =?UTF-8?q?=EA=B0=84=EC=9D=84=20=EC=82=AD=EC=A0=9C=ED=95=98=EB=A0=A4=20?= =?UTF-8?q?=ED=95=A0=20=EB=95=8C=20=EC=98=88=EC=99=B8=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: ehbeak --- README.md | 2 +- .../roomescape/repository/ReservationDAO.java | 6 ++ .../repository/ReservationRepository.java | 2 + .../service/ReservationTimeService.java | 10 +++- .../service/FakeReservationRepository.java | 55 +++++++++++++++++++ .../service/ReservationServiceTest.java | 37 ------------- .../service/ReservationTimeServiceTest.java | 14 ++++- 7 files changed, 86 insertions(+), 40 deletions(-) create mode 100644 src/test/java/roomescape/service/FakeReservationRepository.java diff --git a/README.md b/README.md index 630825cf79..6e797c0d2d 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ - 예약자명: null, "" - 날짜: null, "", yyyy-MM-dd이 아닌 경우 - 시간: null, "", HH:mm이 아닌 경우 - - [ ] 특정 시간에 대한 예약이 존재하는데, 그 시간을 삭제하려 할 때 + - [x] 특정 시간에 대한 예약이 존재하는데, 그 시간을 삭제하려 할 때 - [x] 존재하지 않는 id를 가진 데이터에 접근하려 할 때 - [x] 지나간 날짜와 시간에 대한 예약 생성 불가능 - [ ] 중복 예약 불가능 diff --git a/src/main/java/roomescape/repository/ReservationDAO.java b/src/main/java/roomescape/repository/ReservationDAO.java index feb344b6a0..769e864bec 100644 --- a/src/main/java/roomescape/repository/ReservationDAO.java +++ b/src/main/java/roomescape/repository/ReservationDAO.java @@ -70,4 +70,10 @@ public Long countReservationById(long id) { String sql = "select count(id) from reservation where id = ?"; return jdbcTemplate.queryForObject(sql, (resultSet, ignored) -> resultSet.getLong(1), id); } + + @Override + public Long countReservationByTimeId(long timeId) { + String sql = "select count(id) from reservation where time_id = ?"; + return jdbcTemplate.queryForObject(sql, (resultSet, ignored) -> resultSet.getLong(1), timeId); + } } diff --git a/src/main/java/roomescape/repository/ReservationRepository.java b/src/main/java/roomescape/repository/ReservationRepository.java index 6c8d1bb6d2..2a464d089f 100644 --- a/src/main/java/roomescape/repository/ReservationRepository.java +++ b/src/main/java/roomescape/repository/ReservationRepository.java @@ -11,4 +11,6 @@ public interface ReservationRepository { long deleteReservation(long id); Long countReservationById(long id); + + Long countReservationByTimeId(long timeId); } diff --git a/src/main/java/roomescape/service/ReservationTimeService.java b/src/main/java/roomescape/service/ReservationTimeService.java index cc453edb3a..95f148d084 100644 --- a/src/main/java/roomescape/service/ReservationTimeService.java +++ b/src/main/java/roomescape/service/ReservationTimeService.java @@ -3,16 +3,20 @@ import java.util.List; import org.springframework.stereotype.Service; import roomescape.controller.request.ReservationTimeRequest; +import roomescape.exception.BadRequestException; import roomescape.exception.NotFoundException; import roomescape.model.ReservationTime; +import roomescape.repository.ReservationRepository; import roomescape.repository.ReservationTimeRepository; @Service public class ReservationTimeService { + private final ReservationRepository reservationRepository; private final ReservationTimeRepository reservationTimeRepository; - public ReservationTimeService(ReservationTimeRepository reservationTimeRepository) { + public ReservationTimeService(ReservationRepository reservationRepository, ReservationTimeRepository reservationTimeRepository) { + this.reservationRepository = reservationRepository; this.reservationTimeRepository = reservationTimeRepository; } @@ -34,6 +38,10 @@ public void deleteReservationTime(long id) { if (count == null || count <= 0) { throw new NotFoundException("[ERROR] 존재하지 않는 시간입니다."); } + Long countOfReservationUsingTime = reservationRepository.countReservationByTimeId(id); + if (countOfReservationUsingTime == null || countOfReservationUsingTime > 0) { + throw new BadRequestException("[ERROR] 해당 시간을 사용하고 있는 예약이 있습니다."); + } reservationTimeRepository.deleteReservationTime(id); } } diff --git a/src/test/java/roomescape/service/FakeReservationRepository.java b/src/test/java/roomescape/service/FakeReservationRepository.java new file mode 100644 index 0000000000..c4e3a9cb2b --- /dev/null +++ b/src/test/java/roomescape/service/FakeReservationRepository.java @@ -0,0 +1,55 @@ +package roomescape.service; + +import roomescape.model.Reservation; +import roomescape.model.ReservationTime; +import roomescape.repository.ReservationRepository; + +import java.time.LocalDate; +import java.time.LocalTime; +import java.util.ArrayList; +import java.util.List; +import java.util.NoSuchElementException; + +class FakeReservationRepository implements ReservationRepository { + + private List reservations = new ArrayList<>(List.of( + new Reservation(1, "브라운", LocalDate.of(2023, 8, 5), + new ReservationTime(1, LocalTime.of(10, 0))), + new Reservation(1, "리사", LocalDate.of(2023, 8, 1), + new ReservationTime(2, LocalTime.of(11, 0))))); + + @Override + public List getAllReservations() { + return reservations; + } + + @Override + public Reservation addReservation(Reservation reservation) { + reservations.add(reservation); + return reservation; + } + + @Override + public long deleteReservation(long id) { + Reservation foundReservation = reservations.stream() + .filter(reservation -> reservation.getId() == id) + .findFirst() + .orElseThrow(() -> new NoSuchElementException("아이디가 존재하지 않습니다.")); + reservations.remove(foundReservation); + return id; + } + + @Override + public Long countReservationById(long id) { + return reservations.stream() + .filter(reservation -> reservation.getId() == id) + .count(); + } + + @Override + public Long countReservationByTimeId(long timeId) { + return reservations.stream() + .filter(reservation -> reservation.getTime().getId() == timeId) + .count(); + } +} \ No newline at end of file diff --git a/src/test/java/roomescape/service/ReservationServiceTest.java b/src/test/java/roomescape/service/ReservationServiceTest.java index 5a2ae3fbf9..37793288c3 100644 --- a/src/test/java/roomescape/service/ReservationServiceTest.java +++ b/src/test/java/roomescape/service/ReservationServiceTest.java @@ -79,41 +79,4 @@ void should_not_throw_exception_when_later_date() { assertThatCode(() -> reservationService.addReservation(request)) .doesNotThrowAnyException(); } - - class FakeReservationRepository implements ReservationRepository { - - private List reservations = new ArrayList<>(List.of( - new Reservation(1, "브라운", LocalDate.of(2023, 8, 5), - new ReservationTime(1, LocalTime.of(10, 0))), - new Reservation(1, "리사", LocalDate.of(2023, 8, 1), - new ReservationTime(2, LocalTime.of(11, 0))))); - - @Override - public List getAllReservations() { - return reservations; - } - - @Override - public Reservation addReservation(Reservation reservation) { - reservations.add(reservation); - return reservation; - } - - @Override - public long deleteReservation(long id) { - Reservation foundReservation = reservations.stream() - .filter(reservation -> reservation.getId() == id) - .findFirst() - .orElseThrow(() -> new NoSuchElementException("아이디가 존재하지 않습니다.")); - reservations.remove(foundReservation); - return id; - } - - @Override - public Long countReservationById(long id) { - return reservations.stream() - .filter(reservation -> reservation.getId() == id) - .count(); - } - } } diff --git a/src/test/java/roomescape/service/ReservationTimeServiceTest.java b/src/test/java/roomescape/service/ReservationTimeServiceTest.java index 0de6ba6906..aaf3b88db6 100644 --- a/src/test/java/roomescape/service/ReservationTimeServiceTest.java +++ b/src/test/java/roomescape/service/ReservationTimeServiceTest.java @@ -7,13 +7,17 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import roomescape.controller.request.ReservationTimeRequest; +import roomescape.exception.BadRequestException; import roomescape.exception.NotFoundException; import roomescape.model.ReservationTime; import static org.assertj.core.api.Assertions.*; class ReservationTimeServiceTest { - ReservationTimeService reservationTimeService = new ReservationTimeService(new FakeReservationTimeRepository()); + ReservationTimeService reservationTimeService = new ReservationTimeService( + new FakeReservationRepository(), + new FakeReservationTimeRepository() + ); @DisplayName("모든 예약 시간을 반환한다") @Test @@ -60,4 +64,12 @@ void should_not_throw_exception_when_exist_id() { assertThatCode(() -> reservationTimeService.deleteReservationTime(1)) .doesNotThrowAnyException(); } + + @DisplayName("특정 시간에 대핸 예약이 존재하는데, 그 시간을 삭제하려 할 때 예외가 발생한다.") + @Test + void should_throw_exception_when_exist_reservation_using_time() { + assertThatThrownBy(() -> reservationTimeService.deleteReservationTime(1)) + .isInstanceOf(BadRequestException.class) + .hasMessage("[ERROR] 해당 시간을 사용하고 있는 예약이 있습니다."); + } } From 03b8ec83d83776ff02ad7bc4987413983dd43a45 Mon Sep 17 00:00:00 2001 From: SCY Date: Wed, 1 May 2024 14:18:23 +0900 Subject: [PATCH 12/74] =?UTF-8?q?feat(ReservationTimeService):=20=EC=98=88?= =?UTF-8?q?=EC=95=BD=20=EC=8B=9C=EA=B0=84=20=EC=A4=91=EB=B3=B5=20=EC=8B=9C?= =?UTF-8?q?=20=EC=98=88=EC=99=B8=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: ehbeak --- README.md | 1 + .../roomescape/exception/DuplicatedException.java | 8 ++++++++ .../roomescape/repository/ReservationTimeDAO.java | 8 ++++++++ .../repository/ReservationTimeRepository.java | 3 +++ .../roomescape/service/ReservationTimeService.java | 9 ++++++++- .../controller/ReservationTimeControllerTest.java | 2 +- .../service/FakeReservationRepository.java | 2 +- .../service/FakeReservationTimeRepository.java | 7 +++++++ .../roomescape/service/ReservationServiceTest.java | 12 ++---------- .../service/ReservationTimeServiceTest.java | 14 ++++++++++++-- 10 files changed, 51 insertions(+), 15 deletions(-) create mode 100644 src/main/java/roomescape/exception/DuplicatedException.java diff --git a/README.md b/README.md index 6e797c0d2d..a7b899c9ab 100644 --- a/README.md +++ b/README.md @@ -10,3 +10,4 @@ - [x] 존재하지 않는 id를 가진 데이터에 접근하려 할 때 - [x] 지나간 날짜와 시간에 대한 예약 생성 불가능 - [ ] 중복 예약 불가능 + - [x] 예약 시간 중복 불가능 diff --git a/src/main/java/roomescape/exception/DuplicatedException.java b/src/main/java/roomescape/exception/DuplicatedException.java new file mode 100644 index 0000000000..9afbc9cf00 --- /dev/null +++ b/src/main/java/roomescape/exception/DuplicatedException.java @@ -0,0 +1,8 @@ +package roomescape.exception; + +public class DuplicatedException extends RuntimeException { + + public DuplicatedException(String message) { + super(message); + } +} diff --git a/src/main/java/roomescape/repository/ReservationTimeDAO.java b/src/main/java/roomescape/repository/ReservationTimeDAO.java index 3fa925261a..9c55543199 100644 --- a/src/main/java/roomescape/repository/ReservationTimeDAO.java +++ b/src/main/java/roomescape/repository/ReservationTimeDAO.java @@ -1,5 +1,6 @@ package roomescape.repository; +import java.time.LocalTime; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -64,4 +65,11 @@ public Long countReservationTimeById(long id) { return jdbcTemplate.queryForObject(sql, (resultSet, ignored) -> resultSet.getLong(1), id); } + + @Override + public Long countReservationTimeByStartAt(LocalTime startAt) { + String sql = "select count(id) from reservation_time where start_at = ?"; + return jdbcTemplate.queryForObject(sql, (resultSet, ignored) -> + resultSet.getLong(1), startAt); + } } diff --git a/src/main/java/roomescape/repository/ReservationTimeRepository.java b/src/main/java/roomescape/repository/ReservationTimeRepository.java index 0847352c34..2d1c41a439 100644 --- a/src/main/java/roomescape/repository/ReservationTimeRepository.java +++ b/src/main/java/roomescape/repository/ReservationTimeRepository.java @@ -1,5 +1,6 @@ package roomescape.repository; +import java.time.LocalTime; import java.util.List; import roomescape.model.ReservationTime; @@ -13,4 +14,6 @@ public interface ReservationTimeRepository { void deleteReservationTime(long id); Long countReservationTimeById(long id); + + Long countReservationTimeByStartAt(LocalTime startAt); } diff --git a/src/main/java/roomescape/service/ReservationTimeService.java b/src/main/java/roomescape/service/ReservationTimeService.java index 95f148d084..a531f563c6 100644 --- a/src/main/java/roomescape/service/ReservationTimeService.java +++ b/src/main/java/roomescape/service/ReservationTimeService.java @@ -1,9 +1,11 @@ package roomescape.service; +import java.time.LocalTime; import java.util.List; import org.springframework.stereotype.Service; import roomescape.controller.request.ReservationTimeRequest; import roomescape.exception.BadRequestException; +import roomescape.exception.DuplicatedException; import roomescape.exception.NotFoundException; import roomescape.model.ReservationTime; import roomescape.repository.ReservationRepository; @@ -25,7 +27,12 @@ public List findAllReservationTimes() { } public ReservationTime addReservationTime(ReservationTimeRequest request) { - ReservationTime reservationTime = new ReservationTime(request.getStartAt()); + LocalTime startAt = request.getStartAt(); + Long countReservationTimeByStartAt = reservationTimeRepository.countReservationTimeByStartAt(startAt); + if (countReservationTimeByStartAt == null || countReservationTimeByStartAt > 0) { + throw new DuplicatedException("[ERROR] 중복되는 시간은 추가할 수 없습니다."); + } + ReservationTime reservationTime = new ReservationTime(startAt); return reservationTimeRepository.addReservationTime(reservationTime); } diff --git a/src/test/java/roomescape/controller/ReservationTimeControllerTest.java b/src/test/java/roomescape/controller/ReservationTimeControllerTest.java index 8923385e9d..733598d9f3 100644 --- a/src/test/java/roomescape/controller/ReservationTimeControllerTest.java +++ b/src/test/java/roomescape/controller/ReservationTimeControllerTest.java @@ -42,7 +42,7 @@ void should_get_reservation_times() { @DisplayName("예약 시간을 추가한다") @Test void should_add_reservation_times() { - ReservationTimeRequest request = new ReservationTimeRequest("10:00"); + ReservationTimeRequest request = new ReservationTimeRequest("12:00"); RestAssured.given().log().all() .contentType(ContentType.JSON) diff --git a/src/test/java/roomescape/service/FakeReservationRepository.java b/src/test/java/roomescape/service/FakeReservationRepository.java index c4e3a9cb2b..1724bd0b14 100644 --- a/src/test/java/roomescape/service/FakeReservationRepository.java +++ b/src/test/java/roomescape/service/FakeReservationRepository.java @@ -14,7 +14,7 @@ class FakeReservationRepository implements ReservationRepository { private List reservations = new ArrayList<>(List.of( new Reservation(1, "브라운", LocalDate.of(2023, 8, 5), - new ReservationTime(1, LocalTime.of(10, 0))), + new ReservationTime(2, LocalTime.of(11, 0))), new Reservation(1, "리사", LocalDate.of(2023, 8, 1), new ReservationTime(2, LocalTime.of(11, 0))))); diff --git a/src/test/java/roomescape/service/FakeReservationTimeRepository.java b/src/test/java/roomescape/service/FakeReservationTimeRepository.java index 182a73e65e..51229c1a36 100644 --- a/src/test/java/roomescape/service/FakeReservationTimeRepository.java +++ b/src/test/java/roomescape/service/FakeReservationTimeRepository.java @@ -49,4 +49,11 @@ public Long countReservationTimeById(long id) { .filter(reservationTime -> reservationTime.getId() == id) .count(); } + + @Override + public Long countReservationTimeByStartAt(LocalTime startAt) { + return reservationTimes.stream() + .filter(reservationTime -> reservationTime.getStartAt() == startAt) + .count(); + } } diff --git a/src/test/java/roomescape/service/ReservationServiceTest.java b/src/test/java/roomescape/service/ReservationServiceTest.java index 37793288c3..c648b7cf2a 100644 --- a/src/test/java/roomescape/service/ReservationServiceTest.java +++ b/src/test/java/roomescape/service/ReservationServiceTest.java @@ -1,21 +1,13 @@ package roomescape.service; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.util.ArrayList; -import java.util.List; -import java.util.NoSuchElementException; - -import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import roomescape.controller.request.ReservationRequest; import roomescape.exception.BadRequestException; import roomescape.exception.NotFoundException; import roomescape.model.Reservation; -import roomescape.model.ReservationTime; -import roomescape.repository.ReservationRepository; + +import java.util.List; import static org.assertj.core.api.Assertions.*; diff --git a/src/test/java/roomescape/service/ReservationTimeServiceTest.java b/src/test/java/roomescape/service/ReservationTimeServiceTest.java index aaf3b88db6..d6b63148d0 100644 --- a/src/test/java/roomescape/service/ReservationTimeServiceTest.java +++ b/src/test/java/roomescape/service/ReservationTimeServiceTest.java @@ -8,6 +8,7 @@ import org.junit.jupiter.api.Test; import roomescape.controller.request.ReservationTimeRequest; import roomescape.exception.BadRequestException; +import roomescape.exception.DuplicatedException; import roomescape.exception.NotFoundException; import roomescape.model.ReservationTime; @@ -37,7 +38,7 @@ void should_get_reservation_time() { @Test void should_add_reservation_times() { ReservationTime reservationTime - = reservationTimeService.addReservationTime(new ReservationTimeRequest("10:00")); + = reservationTimeService.addReservationTime(new ReservationTimeRequest("12:00")); List allReservationTimes = reservationTimeService.findAllReservationTimes(); assertThat(allReservationTimes).hasSize(3); } @@ -68,8 +69,17 @@ void should_not_throw_exception_when_exist_id() { @DisplayName("특정 시간에 대핸 예약이 존재하는데, 그 시간을 삭제하려 할 때 예외가 발생한다.") @Test void should_throw_exception_when_exist_reservation_using_time() { - assertThatThrownBy(() -> reservationTimeService.deleteReservationTime(1)) + assertThatThrownBy(() -> reservationTimeService.deleteReservationTime(2)) .isInstanceOf(BadRequestException.class) .hasMessage("[ERROR] 해당 시간을 사용하고 있는 예약이 있습니다."); } + + @DisplayName("존재하는 시간을 추가하려 할 때 예외가 발생한다.") + @Test + void should_throw_exception_when_add_exist_time() { + ReservationTimeRequest request = new ReservationTimeRequest("10:00"); + assertThatThrownBy(() -> reservationTimeService.addReservationTime(request)) + .isInstanceOf(DuplicatedException.class) + .hasMessage("[ERROR] 중복되는 시간은 추가할 수 없습니다."); + } } From 23794461fa5acfac3c064181fdd119a3a6b43f96 Mon Sep 17 00:00:00 2001 From: SCY Date: Wed, 1 May 2024 14:28:21 +0900 Subject: [PATCH 13/74] =?UTF-8?q?feat(ReservationService):=20=EC=98=88?= =?UTF-8?q?=EC=95=BD=20=EC=A4=91=EB=B3=B5=20=EC=8B=9C=20=EC=98=88=EC=99=B8?= =?UTF-8?q?=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: ehbeak --- README.md | 4 ++-- .../java/roomescape/repository/ReservationDAO.java | 7 +++++++ .../roomescape/repository/ReservationRepository.java | 3 +++ .../java/roomescape/service/ReservationService.java | 7 +++++-- .../service/FakeReservationRepository.java | 12 ++++++++++-- .../roomescape/service/ReservationServiceTest.java | 11 +++++++++++ 6 files changed, 38 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index a7b899c9ab..d4ad23b83d 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ ## 기능 요구사항 -- [ ] 예외 처리 +- [x] 예외 처리 - [x] 시간 생성 시 시작 시간에 유효하지 않은 값이 입력되었을 때 - null, "", HH:mm이 아닌 경우 - [x] 예약 생성 시 예약자명, 날짜, 시간에 유효하지 않은 값이 입력 되었을 때 @@ -9,5 +9,5 @@ - [x] 특정 시간에 대한 예약이 존재하는데, 그 시간을 삭제하려 할 때 - [x] 존재하지 않는 id를 가진 데이터에 접근하려 할 때 - [x] 지나간 날짜와 시간에 대한 예약 생성 불가능 - - [ ] 중복 예약 불가능 + - [x] 중복 예약 불가능 - [x] 예약 시간 중복 불가능 diff --git a/src/main/java/roomescape/repository/ReservationDAO.java b/src/main/java/roomescape/repository/ReservationDAO.java index 769e864bec..16bc8ab2f4 100644 --- a/src/main/java/roomescape/repository/ReservationDAO.java +++ b/src/main/java/roomescape/repository/ReservationDAO.java @@ -1,5 +1,6 @@ package roomescape.repository; +import java.time.LocalDate; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -76,4 +77,10 @@ public Long countReservationByTimeId(long timeId) { String sql = "select count(id) from reservation where time_id = ?"; return jdbcTemplate.queryForObject(sql, (resultSet, ignored) -> resultSet.getLong(1), timeId); } + + @Override + public Long countReservationByDateAndTimeId(LocalDate date, long timeId) { + String sql = "select count(id) from reservation where date = ? and time_id = ?"; + return jdbcTemplate.queryForObject(sql, (resultSet, ignored) -> resultSet.getLong(1), date, timeId); + } } diff --git a/src/main/java/roomescape/repository/ReservationRepository.java b/src/main/java/roomescape/repository/ReservationRepository.java index 2a464d089f..990be88a2d 100644 --- a/src/main/java/roomescape/repository/ReservationRepository.java +++ b/src/main/java/roomescape/repository/ReservationRepository.java @@ -1,5 +1,6 @@ package roomescape.repository; +import java.time.LocalDate; import java.util.List; import roomescape.model.Reservation; @@ -13,4 +14,6 @@ public interface ReservationRepository { Long countReservationById(long id); Long countReservationByTimeId(long timeId); + + Long countReservationByDateAndTimeId(LocalDate date, long timeId); } diff --git a/src/main/java/roomescape/service/ReservationService.java b/src/main/java/roomescape/service/ReservationService.java index 05835adb0e..3f61ad0638 100644 --- a/src/main/java/roomescape/service/ReservationService.java +++ b/src/main/java/roomescape/service/ReservationService.java @@ -1,12 +1,11 @@ package roomescape.service; -import java.time.LocalDate; import java.time.LocalDateTime; -import java.time.LocalTime; import java.util.List; import org.springframework.stereotype.Service; import roomescape.controller.request.ReservationRequest; import roomescape.exception.BadRequestException; +import roomescape.exception.DuplicatedException; import roomescape.exception.NotFoundException; import roomescape.model.Reservation; import roomescape.model.ReservationTime; @@ -35,6 +34,10 @@ public Reservation addReservation(ReservationRequest request) { if (reservationDateTime.isBefore(LocalDateTime.now())) { throw new BadRequestException("[ERROR] 현재 이전 예약은 할 수 없습니다."); } + Long countReservation = reservationRepository.countReservationByDateAndTimeId(request.getDate(), request.getTimeId()); + if (countReservation == null || countReservation > 0) { + throw new DuplicatedException("[ERROR] 중복되는 예약은 추가할 수 없습니다."); + } return reservationRepository.addReservation(new Reservation(request.getName(), request.getDate(), reservationTime)); } diff --git a/src/test/java/roomescape/service/FakeReservationRepository.java b/src/test/java/roomescape/service/FakeReservationRepository.java index 1724bd0b14..99cf92fda1 100644 --- a/src/test/java/roomescape/service/FakeReservationRepository.java +++ b/src/test/java/roomescape/service/FakeReservationRepository.java @@ -13,9 +13,9 @@ class FakeReservationRepository implements ReservationRepository { private List reservations = new ArrayList<>(List.of( - new Reservation(1, "브라운", LocalDate.of(2023, 8, 5), + new Reservation(1, "브라운", LocalDate.of(2030, 8, 5), new ReservationTime(2, LocalTime.of(11, 0))), - new Reservation(1, "리사", LocalDate.of(2023, 8, 1), + new Reservation(1, "리사", LocalDate.of(2030, 8, 1), new ReservationTime(2, LocalTime.of(11, 0))))); @Override @@ -52,4 +52,12 @@ public Long countReservationByTimeId(long timeId) { .filter(reservation -> reservation.getTime().getId() == timeId) .count(); } + + @Override + public Long countReservationByDateAndTimeId(LocalDate date, long timeId) { + return reservations.stream() + .filter(reservation -> reservation.getDate().isEqual(date) + && reservation.getTime().getId() == timeId) + .count(); + } } \ No newline at end of file diff --git a/src/test/java/roomescape/service/ReservationServiceTest.java b/src/test/java/roomescape/service/ReservationServiceTest.java index c648b7cf2a..ef8e049e2e 100644 --- a/src/test/java/roomescape/service/ReservationServiceTest.java +++ b/src/test/java/roomescape/service/ReservationServiceTest.java @@ -3,7 +3,9 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import roomescape.controller.request.ReservationRequest; +import roomescape.controller.request.ReservationTimeRequest; import roomescape.exception.BadRequestException; +import roomescape.exception.DuplicatedException; import roomescape.exception.NotFoundException; import roomescape.model.Reservation; @@ -71,4 +73,13 @@ void should_not_throw_exception_when_later_date() { assertThatCode(() -> reservationService.addReservation(request)) .doesNotThrowAnyException(); } + + @DisplayName("날짜, 시간이 일치하는 예약을 추가하려 할 때 예외가 발생한다.") + @Test + void should_throw_exception_when_add_exist_reservation() { + ReservationRequest request = new ReservationRequest("2030-08-05", "배키", 2); + assertThatThrownBy(() -> reservationService.addReservation(request)) + .isInstanceOf(DuplicatedException.class) + .hasMessage("[ERROR] 중복되는 예약은 추가할 수 없습니다."); + } } From a46351f65000d15d082578241f772d992a6f7588 Mon Sep 17 00:00:00 2001 From: SCY Date: Wed, 1 May 2024 14:39:34 +0900 Subject: [PATCH 14/74] =?UTF-8?q?docs(README):=202=EB=8B=A8=EA=B3=84=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EC=9A=94=EA=B5=AC=EC=82=AC=ED=95=AD=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: ehbeak --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index d4ad23b83d..cb90a87a96 100644 --- a/README.md +++ b/README.md @@ -11,3 +11,10 @@ - [x] 지나간 날짜와 시간에 대한 예약 생성 불가능 - [x] 중복 예약 불가능 - [x] 예약 시간 중복 불가능 + +- [ ] '테마' 도메인 추가 + - [ ] 모든 테마는 시작 시간과 소요 시간이 동일 +- [ ] 테마 관리 페이지 조회 +- [ ] 테마 추가 API +- [ ] 테마 삭제 API +- [ ] 테마 조회 API From ced829023dc07047207e41a88046f87a829edec9 Mon Sep 17 00:00:00 2001 From: SCY Date: Wed, 1 May 2024 14:41:20 +0900 Subject: [PATCH 15/74] =?UTF-8?q?chore(schema):=20DDL=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: ehbeak --- src/main/resources/schema.sql | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql index dd05ed17f4..e5c82b2155 100644 --- a/src/main/resources/schema.sql +++ b/src/main/resources/schema.sql @@ -5,14 +5,25 @@ CREATE TABLE reservation_time PRIMARY KEY (id) ); +CREATE TABLE theme +( + id BIGINT NOT NULL AUTO_INCREMENT, + name VARCHAR(255) NOT NULL, + description VARCHAR(255) NOT NULL, + thumbnail VARCHAR(255) NOT NULL, + PRIMARY KEY (id) +); + CREATE TABLE reservation ( id BIGINT NOT NULL AUTO_INCREMENT, name VARCHAR(255) NOT NULL, date VARCHAR(255) NOT NULL, time_id BIGINT, + theme_id BIGINT, -- 컬럼 추가 PRIMARY KEY (id), - FOREIGN KEY (time_id) REFERENCES reservation_time (id) + FOREIGN KEY (time_id) REFERENCES reservation_time (id), + FOREIGN KEY (theme_id) REFERENCES theme (id) -- 외래키 추가 ); INSERT INTO reservation_time (start_at) VALUES ('10:00'); From 447436af721b461437b74fa7e5fbc11abdeb6a9f Mon Sep 17 00:00:00 2001 From: SCY Date: Wed, 1 May 2024 14:43:19 +0900 Subject: [PATCH 16/74] =?UTF-8?q?feat(StaticPageController):=20=ED=85=8C?= =?UTF-8?q?=EB=A7=88=20=EA=B4=80=EB=A6=AC=20=ED=8E=98=EC=9D=B4=EC=A7=80=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: ehbeak --- README.md | 2 +- .../java/roomescape/controller/StaticPageController.java | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index cb90a87a96..95670823ca 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ - [ ] '테마' 도메인 추가 - [ ] 모든 테마는 시작 시간과 소요 시간이 동일 -- [ ] 테마 관리 페이지 조회 +- [x] 테마 관리 페이지 조회 - [ ] 테마 추가 API - [ ] 테마 삭제 API - [ ] 테마 조회 API diff --git a/src/main/java/roomescape/controller/StaticPageController.java b/src/main/java/roomescape/controller/StaticPageController.java index 98bcedd65f..85b4742994 100644 --- a/src/main/java/roomescape/controller/StaticPageController.java +++ b/src/main/java/roomescape/controller/StaticPageController.java @@ -12,11 +12,16 @@ public String getAdminPage() { @GetMapping("/admin/reservation") public String getReservationPage() { - return "admin/reservation"; + return "admin/reservation-new"; } @GetMapping("/admin/time") public String getReservationTimePage() { return "admin/time"; } + + @GetMapping("/admin/theme") + public String getThemePage() { + return "admin/theme"; + } } From 11601777695e5b82d7a0dad64e7b2effaa35a2aa Mon Sep 17 00:00:00 2001 From: SCY Date: Wed, 1 May 2024 14:46:07 +0900 Subject: [PATCH 17/74] =?UTF-8?q?feat(Theme):=20=ED=85=8C=EB=A7=88=20?= =?UTF-8?q?=EB=8F=84=EB=A9=94=EC=9D=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: ehbeak --- README.md | 2 +- .../java/roomescape/model/Reservation.java | 5 ++++ src/main/java/roomescape/model/Theme.java | 29 +++++++++++++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 src/main/java/roomescape/model/Theme.java diff --git a/README.md b/README.md index 95670823ca..746b2cb0db 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ - [x] 중복 예약 불가능 - [x] 예약 시간 중복 불가능 -- [ ] '테마' 도메인 추가 +- [x] '테마' 도메인 추가 - [ ] 모든 테마는 시작 시간과 소요 시간이 동일 - [x] 테마 관리 페이지 조회 - [ ] 테마 추가 API diff --git a/src/main/java/roomescape/model/Reservation.java b/src/main/java/roomescape/model/Reservation.java index 5105c5f180..2644d178ff 100644 --- a/src/main/java/roomescape/model/Reservation.java +++ b/src/main/java/roomescape/model/Reservation.java @@ -8,6 +8,7 @@ public class Reservation { private String name; private LocalDate date; private ReservationTime time; + private Theme theme; private Reservation() { } @@ -40,4 +41,8 @@ public LocalDate getDate() { public ReservationTime getTime() { return time; } + + public Theme getTheme() { + return theme; + } } diff --git a/src/main/java/roomescape/model/Theme.java b/src/main/java/roomescape/model/Theme.java new file mode 100644 index 0000000000..c5569514ee --- /dev/null +++ b/src/main/java/roomescape/model/Theme.java @@ -0,0 +1,29 @@ +package roomescape.model; + +public class Theme { + + private String name; + private String description; + private String thumbnail; + + private Theme() { + } + + public Theme(String name, String description, String thumbnail) { + this.name = name; + this.description = description; + this.thumbnail = thumbnail; + } + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + + public String getThumbnail() { + return thumbnail; + } +} From 83763302c9f0ca9759238f9ab8a97872e389a0ea Mon Sep 17 00:00:00 2001 From: SCY Date: Wed, 1 May 2024 15:14:25 +0900 Subject: [PATCH 18/74] =?UTF-8?q?feat(theme):=20=ED=85=8C=EB=A7=88=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20API=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: ehbeak --- README.md | 2 +- .../controller/ReservationController.java | 1 - .../controller/ThemeController.java | 25 ++++++++ src/main/java/roomescape/model/Theme.java | 8 ++- .../java/roomescape/repository/ThemeDAO.java | 40 ++++++++++++ .../repository/ThemeRepository.java | 14 +++++ .../java/roomescape/service/ThemeService.java | 21 +++++++ .../controller/ThemeControllerTest.java | 46 ++++++++++++++ .../roomescape/repository/ThemeDAOTest.java | 61 +++++++++++++++++++ .../service/FakeThemeRepository.java | 31 ++++++++++ .../roomescape/service/ThemeServiceTest.java | 16 +++++ 11 files changed, 262 insertions(+), 3 deletions(-) create mode 100644 src/main/java/roomescape/controller/ThemeController.java create mode 100644 src/main/java/roomescape/repository/ThemeDAO.java create mode 100644 src/main/java/roomescape/repository/ThemeRepository.java create mode 100644 src/main/java/roomescape/service/ThemeService.java create mode 100644 src/test/java/roomescape/controller/ThemeControllerTest.java create mode 100644 src/test/java/roomescape/repository/ThemeDAOTest.java create mode 100644 src/test/java/roomescape/service/FakeThemeRepository.java create mode 100644 src/test/java/roomescape/service/ThemeServiceTest.java diff --git a/README.md b/README.md index 746b2cb0db..823084e78a 100644 --- a/README.md +++ b/README.md @@ -17,4 +17,4 @@ - [x] 테마 관리 페이지 조회 - [ ] 테마 추가 API - [ ] 테마 삭제 API -- [ ] 테마 조회 API +- [x] 테마 조회 API diff --git a/src/main/java/roomescape/controller/ReservationController.java b/src/main/java/roomescape/controller/ReservationController.java index a84d043a4f..4afcff4755 100644 --- a/src/main/java/roomescape/controller/ReservationController.java +++ b/src/main/java/roomescape/controller/ReservationController.java @@ -22,7 +22,6 @@ public ReservationController(ReservationService reservationService) { this.reservationService = reservationService; } - @GetMapping("/reservations") public ResponseEntity> getReservations() { return ResponseEntity.ok(reservationService.findAllReservations()); diff --git a/src/main/java/roomescape/controller/ThemeController.java b/src/main/java/roomescape/controller/ThemeController.java new file mode 100644 index 0000000000..4fe62c3216 --- /dev/null +++ b/src/main/java/roomescape/controller/ThemeController.java @@ -0,0 +1,25 @@ +package roomescape.controller; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RestController; +import roomescape.model.Theme; +import roomescape.service.ThemeService; + +import java.util.List; + +@RestController +public class ThemeController { + + private final ThemeService themeService; + + public ThemeController(ThemeService themeService) { + this.themeService = themeService; + } + + @GetMapping("/themes") + public ResponseEntity> getThemes() { + return ResponseEntity.ok(themeService.findAllThemes()); + } +} diff --git a/src/main/java/roomescape/model/Theme.java b/src/main/java/roomescape/model/Theme.java index c5569514ee..6dc9e89a0f 100644 --- a/src/main/java/roomescape/model/Theme.java +++ b/src/main/java/roomescape/model/Theme.java @@ -2,6 +2,7 @@ public class Theme { + private long id; private String name; private String description; private String thumbnail; @@ -9,12 +10,17 @@ public class Theme { private Theme() { } - public Theme(String name, String description, String thumbnail) { + public Theme(long id, String name, String description, String thumbnail) { + this.id = id; this.name = name; this.description = description; this.thumbnail = thumbnail; } + public long getId() { + return id; + } + public String getName() { return name; } diff --git a/src/main/java/roomescape/repository/ThemeDAO.java b/src/main/java/roomescape/repository/ThemeDAO.java new file mode 100644 index 0000000000..6eab9b753e --- /dev/null +++ b/src/main/java/roomescape/repository/ThemeDAO.java @@ -0,0 +1,40 @@ +package roomescape.repository; + +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Repository; +import roomescape.model.ReservationTime; +import roomescape.model.Theme; + +import java.util.List; + +@Repository +public class ThemeDAO implements ThemeRepository { + + private final JdbcTemplate jdbcTemplate; + + public ThemeDAO(JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } + + @Override + public List findAllThemes() { + String sql = "select id, name, description, thumbnail from theme"; + return jdbcTemplate.query(sql, (resultSet, rowNum) -> + new Theme( + resultSet.getLong("id"), + resultSet.getString("name"), + resultSet.getString("description"), + resultSet.getString("thumbnail") + )); + } + + @Override + public Theme addTheme(Theme theme) { + return null; + } + + @Override + public long deleteTheme(long id) { + return 0; + } +} diff --git a/src/main/java/roomescape/repository/ThemeRepository.java b/src/main/java/roomescape/repository/ThemeRepository.java new file mode 100644 index 0000000000..e297ae543b --- /dev/null +++ b/src/main/java/roomescape/repository/ThemeRepository.java @@ -0,0 +1,14 @@ +package roomescape.repository; + +import roomescape.model.Theme; + +import java.util.List; + +public interface ThemeRepository { + + List findAllThemes(); + + Theme addTheme(Theme theme); + + long deleteTheme(long id); +} diff --git a/src/main/java/roomescape/service/ThemeService.java b/src/main/java/roomescape/service/ThemeService.java new file mode 100644 index 0000000000..af2bd9c163 --- /dev/null +++ b/src/main/java/roomescape/service/ThemeService.java @@ -0,0 +1,21 @@ +package roomescape.service; + +import org.springframework.stereotype.Service; +import roomescape.model.Theme; +import roomescape.repository.ThemeRepository; + +import java.util.List; + +@Service +public class ThemeService { + + private final ThemeRepository themeRepository; + + public ThemeService(ThemeRepository themeRepository) { + this.themeRepository = themeRepository; + } + + public List findAllThemes() { + return themeRepository.findAllThemes(); + } +} diff --git a/src/test/java/roomescape/controller/ThemeControllerTest.java b/src/test/java/roomescape/controller/ThemeControllerTest.java new file mode 100644 index 0000000000..fe9116026d --- /dev/null +++ b/src/test/java/roomescape/controller/ThemeControllerTest.java @@ -0,0 +1,46 @@ +package roomescape.controller; + +import io.restassured.RestAssured; +import org.assertj.core.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.jdbc.core.JdbcTemplate; +import org.springframework.test.annotation.DirtiesContext; +import roomescape.model.Reservation; +import roomescape.model.Theme; + +import java.util.List; + +import static org.assertj.core.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.*; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) +@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) +class ThemeControllerTest { + + @Autowired + JdbcTemplate jdbcTemplate; + + @Autowired + private ThemeController themeController; + + @DisplayName("전체 테마를 조회한다.") + @Test + void should_get_themes() { + jdbcTemplate.update("INSERT INTO theme (name, description, thumbnail) VALUES (?, ?, ?)", "에버", "공포", "공포.jpg"); + jdbcTemplate.update("INSERT INTO theme (name, description, thumbnail) VALUES (?, ?, ?)", "배키", "미스터리", "미스터리.jpg"); + jdbcTemplate.update("INSERT INTO theme (name, description, thumbnail) VALUES (?, ?, ?)", "포비", "스릴러", "스릴러.jpg"); + + List themes = RestAssured.given().log().all() + .when().get("/themes") + .then().log().all() + .statusCode(200).extract() + .jsonPath().getList(".", Theme.class); + + Integer count = jdbcTemplate.queryForObject("SELECT count(1) from theme", Integer.class); + + assertThat(themes).hasSize(count); + } +} \ No newline at end of file diff --git a/src/test/java/roomescape/repository/ThemeDAOTest.java b/src/test/java/roomescape/repository/ThemeDAOTest.java new file mode 100644 index 0000000000..8cb96cb9ef --- /dev/null +++ b/src/test/java/roomescape/repository/ThemeDAOTest.java @@ -0,0 +1,61 @@ +package roomescape.repository; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +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.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.simple.SimpleJdbcInsert; +import org.springframework.test.annotation.DirtiesContext; +import roomescape.model.Theme; + +import javax.sql.DataSource; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) +@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) +class ThemeDAOTest { + + @Autowired + ThemeRepository themeRepository; + + @Autowired + JdbcTemplate jdbcTemplate; + + @Autowired + DataSource dataSource; + + SimpleJdbcInsert themeInsertActor; + + @BeforeEach + void setUp() { + jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY FALSE"); + jdbcTemplate.execute("TRUNCATE TABLE theme RESTART IDENTITY"); + jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY TRUE"); + themeInsertActor = new SimpleJdbcInsert(dataSource) + .withTableName("theme") + .usingGeneratedKeyColumns("id"); + insertTheme("에버", "공포", "공포.jpg"); + insertTheme("배키", "미스터리", "미스터리.jpg"); + } + + private void insertTheme(String name, String description, String thumbnail) { + Map parameters = new HashMap<>(3); + parameters.put("name", name); + parameters.put("description", description); + parameters.put("thumbnail", thumbnail); + themeInsertActor.execute(parameters); + } + + @DisplayName("모든 테마를 조회한다.") + @Test + void should_find_all_themes() { + List allThemes = themeRepository.findAllThemes(); + Assertions.assertThat(allThemes).hasSize(2); + } +} \ No newline at end of file diff --git a/src/test/java/roomescape/service/FakeThemeRepository.java b/src/test/java/roomescape/service/FakeThemeRepository.java new file mode 100644 index 0000000000..c689dc88df --- /dev/null +++ b/src/test/java/roomescape/service/FakeThemeRepository.java @@ -0,0 +1,31 @@ +package roomescape.service; + +import roomescape.model.Theme; +import roomescape.repository.ThemeRepository; + +import java.util.ArrayList; +import java.util.List; + +public class FakeThemeRepository implements ThemeRepository { + + private List themes = new ArrayList<>(List.of( + new Theme(1, "에버", "공포", "공포.jpg"), + new Theme(2, "배키", "미스터리", "미스터리.jpg"), + new Theme(3, "포비", "스릴러", "스릴러.jpg") + )); + + @Override + public List findAllThemes() { + return themes; + } + + @Override + public Theme addTheme(Theme theme) { + return null; + } + + @Override + public long deleteTheme(long id) { + return 0; + } +} diff --git a/src/test/java/roomescape/service/ThemeServiceTest.java b/src/test/java/roomescape/service/ThemeServiceTest.java new file mode 100644 index 0000000000..d15987ba28 --- /dev/null +++ b/src/test/java/roomescape/service/ThemeServiceTest.java @@ -0,0 +1,16 @@ +package roomescape.service; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class ThemeServiceTest { + + ThemeService themeService = new ThemeService(new FakeThemeRepository()); + + @DisplayName("테마를 조회한다.") + @Test + void should_find_all_themes() { + Assertions.assertThat(themeService.findAllThemes()).hasSize(3); + } +} \ No newline at end of file From c4e522519cbe518ff4c3cec54047347ef3474573 Mon Sep 17 00:00:00 2001 From: SCY Date: Wed, 1 May 2024 15:32:57 +0900 Subject: [PATCH 19/74] =?UTF-8?q?feat(theme):=20=ED=85=8C=EB=A7=88=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20API=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: ehbeak --- README.md | 2 +- .../controller/ThemeController.java | 13 ++++++++++ .../controller/request/ThemeRequest.java | 26 +++++++++++++++++++ src/main/java/roomescape/model/Theme.java | 6 +++++ .../java/roomescape/repository/ThemeDAO.java | 17 ++++++++++-- .../java/roomescape/service/ThemeService.java | 6 +++++ .../controller/ReservationControllerTest.java | 2 -- .../controller/ThemeControllerTest.java | 26 +++++++++++++++---- .../roomescape/repository/ThemeDAOTest.java | 12 ++++++++- .../service/FakeThemeRepository.java | 7 ++++- .../roomescape/service/ThemeServiceTest.java | 15 +++++++++-- 11 files changed, 118 insertions(+), 14 deletions(-) create mode 100644 src/main/java/roomescape/controller/request/ThemeRequest.java diff --git a/README.md b/README.md index 823084e78a..fee897b943 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,6 @@ - [x] '테마' 도메인 추가 - [ ] 모든 테마는 시작 시간과 소요 시간이 동일 - [x] 테마 관리 페이지 조회 -- [ ] 테마 추가 API +- [x] 테마 추가 API - [ ] 테마 삭제 API - [x] 테마 조회 API diff --git a/src/main/java/roomescape/controller/ThemeController.java b/src/main/java/roomescape/controller/ThemeController.java index 4fe62c3216..41bb6990ee 100644 --- a/src/main/java/roomescape/controller/ThemeController.java +++ b/src/main/java/roomescape/controller/ThemeController.java @@ -3,10 +3,15 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; +import roomescape.controller.request.ThemeRequest; import roomescape.model.Theme; import roomescape.service.ThemeService; +import javax.xml.stream.Location; +import java.net.URI; +import java.net.URL; import java.util.List; @RestController @@ -22,4 +27,12 @@ public ThemeController(ThemeService themeService) { public ResponseEntity> getThemes() { return ResponseEntity.ok(themeService.findAllThemes()); } + + @PostMapping("/themes") + public ResponseEntity addTheme(@RequestBody ThemeRequest themeRequest) { + Theme theme = themeService.addTheme(themeRequest); + return ResponseEntity + .created(URI.create("/themes/" + theme.getId())) + .body(theme); + } } diff --git a/src/main/java/roomescape/controller/request/ThemeRequest.java b/src/main/java/roomescape/controller/request/ThemeRequest.java new file mode 100644 index 0000000000..f5a998629d --- /dev/null +++ b/src/main/java/roomescape/controller/request/ThemeRequest.java @@ -0,0 +1,26 @@ +package roomescape.controller.request; + +public class ThemeRequest { + + private String name; + private String description; + private String thumbnail; + + public ThemeRequest(String name, String description, String thumbnail) { + this.name = name; + this.description = description; + this.thumbnail = thumbnail; + } + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + + public String getThumbnail() { + return thumbnail; + } +} diff --git a/src/main/java/roomescape/model/Theme.java b/src/main/java/roomescape/model/Theme.java index 6dc9e89a0f..295b5f42b2 100644 --- a/src/main/java/roomescape/model/Theme.java +++ b/src/main/java/roomescape/model/Theme.java @@ -17,6 +17,12 @@ public Theme(long id, String name, String description, String thumbnail) { this.thumbnail = thumbnail; } + public Theme(String name, String description, String thumbnail) { + this.name = name; + this.description = description; + this.thumbnail = thumbnail; + } + public long getId() { return id; } diff --git a/src/main/java/roomescape/repository/ThemeDAO.java b/src/main/java/roomescape/repository/ThemeDAO.java index 6eab9b753e..75bfa69bb8 100644 --- a/src/main/java/roomescape/repository/ThemeDAO.java +++ b/src/main/java/roomescape/repository/ThemeDAO.java @@ -1,19 +1,27 @@ package roomescape.repository; import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.simple.SimpleJdbcInsert; import org.springframework.stereotype.Repository; import roomescape.model.ReservationTime; import roomescape.model.Theme; +import javax.sql.DataSource; +import java.util.HashMap; import java.util.List; +import java.util.Map; @Repository public class ThemeDAO implements ThemeRepository { private final JdbcTemplate jdbcTemplate; + private SimpleJdbcInsert insertActor; - public ThemeDAO(JdbcTemplate jdbcTemplate) { + public ThemeDAO(JdbcTemplate jdbcTemplate, DataSource dataSource) { this.jdbcTemplate = jdbcTemplate; + this.insertActor = new SimpleJdbcInsert(dataSource) + .withTableName("theme") + .usingGeneratedKeyColumns("id"); } @Override @@ -30,7 +38,12 @@ public List findAllThemes() { @Override public Theme addTheme(Theme theme) { - return null; + Map parameters = new HashMap<>(1); + parameters.put("name", theme.getName()); + parameters.put("description", theme.getDescription()); + parameters.put("thumbnail", theme.getThumbnail()); + Number newId = insertActor.executeAndReturnKey(parameters); + return new Theme(newId.longValue(), theme.getName(), theme.getDescription(), theme.getThumbnail()); } @Override diff --git a/src/main/java/roomescape/service/ThemeService.java b/src/main/java/roomescape/service/ThemeService.java index af2bd9c163..c6c435f4c7 100644 --- a/src/main/java/roomescape/service/ThemeService.java +++ b/src/main/java/roomescape/service/ThemeService.java @@ -1,6 +1,7 @@ package roomescape.service; import org.springframework.stereotype.Service; +import roomescape.controller.request.ThemeRequest; import roomescape.model.Theme; import roomescape.repository.ThemeRepository; @@ -18,4 +19,9 @@ public ThemeService(ThemeRepository themeRepository) { public List findAllThemes() { return themeRepository.findAllThemes(); } + + public Theme addTheme(ThemeRequest themeRequest) { + Theme theme = new Theme(themeRequest.getName(), themeRequest.getDescription(), themeRequest.getThumbnail()); + return themeRepository.addTheme(theme); + } } diff --git a/src/test/java/roomescape/controller/ReservationControllerTest.java b/src/test/java/roomescape/controller/ReservationControllerTest.java index 243725140c..86707c3c79 100644 --- a/src/test/java/roomescape/controller/ReservationControllerTest.java +++ b/src/test/java/roomescape/controller/ReservationControllerTest.java @@ -47,7 +47,6 @@ void should_get_reservations() { @DisplayName("예약을 추가할 수 있다.") @Test void should_insert_reservation() { - Integer count1 = jdbcTemplate.queryForObject("SELECT count(1) from reservation", Integer.class); ReservationRequest request = new ReservationRequest( "2030-08-05", "브라운", @@ -62,7 +61,6 @@ void should_insert_reservation() { .header("Location", "/reservations/1"); Integer count = jdbcTemplate.queryForObject("SELECT count(1) from reservation", Integer.class); - System.out.println("count = " + count); assertThat(count).isEqualTo(1); } diff --git a/src/test/java/roomescape/controller/ThemeControllerTest.java b/src/test/java/roomescape/controller/ThemeControllerTest.java index fe9116026d..5d9eb70ab9 100644 --- a/src/test/java/roomescape/controller/ThemeControllerTest.java +++ b/src/test/java/roomescape/controller/ThemeControllerTest.java @@ -1,20 +1,19 @@ package roomescape.controller; import io.restassured.RestAssured; -import org.assertj.core.api.Assertions; +import io.restassured.http.ContentType; 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.jdbc.core.JdbcTemplate; import org.springframework.test.annotation.DirtiesContext; -import roomescape.model.Reservation; +import roomescape.controller.request.ThemeRequest; import roomescape.model.Theme; import java.util.List; -import static org.assertj.core.api.Assertions.*; -import static org.junit.jupiter.api.Assertions.*; +import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) @@ -40,7 +39,24 @@ void should_get_themes() { .jsonPath().getList(".", Theme.class); Integer count = jdbcTemplate.queryForObject("SELECT count(1) from theme", Integer.class); - assertThat(themes).hasSize(count); } + + @DisplayName("전체 테마를 추가한다.") + @Test + void should_add_theme() { + ThemeRequest request = new ThemeRequest("에버", "공포", "공포.jpg"); + + RestAssured.given().log().all() + .contentType(ContentType.JSON) + .body(request) + .when().post("/themes") + .then().log().all() + .statusCode(201) + .header("Location", "/themes/1"); + + Integer count = jdbcTemplate.queryForObject("SELECT count(1) from theme", Integer.class); + + assertThat(count).isEqualTo(1); + } } \ No newline at end of file diff --git a/src/test/java/roomescape/repository/ThemeDAOTest.java b/src/test/java/roomescape/repository/ThemeDAOTest.java index 8cb96cb9ef..32e43c7f3a 100644 --- a/src/test/java/roomescape/repository/ThemeDAOTest.java +++ b/src/test/java/roomescape/repository/ThemeDAOTest.java @@ -17,6 +17,8 @@ import java.util.List; import java.util.Map; +import static org.assertj.core.api.Assertions.*; + @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) class ThemeDAOTest { @@ -56,6 +58,14 @@ private void insertTheme(String name, String description, String thumbnail) { @Test void should_find_all_themes() { List allThemes = themeRepository.findAllThemes(); - Assertions.assertThat(allThemes).hasSize(2); + assertThat(allThemes).hasSize(2); + } + + @DisplayName("테마를 저장한다.") + @Test + void should_add_theme() { + Theme theme = new Theme("브라운", "공포", "공포.jpg"); + themeRepository.addTheme(theme); + assertThat(themeRepository.findAllThemes()).hasSize(3); } } \ No newline at end of file diff --git a/src/test/java/roomescape/service/FakeThemeRepository.java b/src/test/java/roomescape/service/FakeThemeRepository.java index c689dc88df..d1a7d3f0cb 100644 --- a/src/test/java/roomescape/service/FakeThemeRepository.java +++ b/src/test/java/roomescape/service/FakeThemeRepository.java @@ -5,6 +5,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.concurrent.atomic.AtomicLong; public class FakeThemeRepository implements ThemeRepository { @@ -14,6 +15,8 @@ public class FakeThemeRepository implements ThemeRepository { new Theme(3, "포비", "스릴러", "스릴러.jpg") )); + private AtomicLong index = new AtomicLong(1L); + @Override public List findAllThemes() { return themes; @@ -21,7 +24,9 @@ public List findAllThemes() { @Override public Theme addTheme(Theme theme) { - return null; + Theme newTheme = new Theme(index.getAndIncrement(), theme.getName(), theme.getDescription(), theme.getThumbnail()); + themes.add(newTheme); + return newTheme; } @Override diff --git a/src/test/java/roomescape/service/ThemeServiceTest.java b/src/test/java/roomescape/service/ThemeServiceTest.java index d15987ba28..1c5b5c283e 100644 --- a/src/test/java/roomescape/service/ThemeServiceTest.java +++ b/src/test/java/roomescape/service/ThemeServiceTest.java @@ -1,8 +1,11 @@ package roomescape.service; -import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import roomescape.controller.request.ThemeRequest; +import roomescape.model.Theme; + +import static org.assertj.core.api.Assertions.*; class ThemeServiceTest { @@ -11,6 +14,14 @@ class ThemeServiceTest { @DisplayName("테마를 조회한다.") @Test void should_find_all_themes() { - Assertions.assertThat(themeService.findAllThemes()).hasSize(3); + assertThat(themeService.findAllThemes()).hasSize(3); + } + + @DisplayName("테마를 저장한다.") + @Test + void should_add_theme() { + ThemeRequest themeRequest = new ThemeRequest("에버", "공포", "공포.jpg"); + Theme theme = themeService.addTheme(themeRequest); + assertThat(themeService.findAllThemes()).hasSize(4); } } \ No newline at end of file From 97dd0d39debaf48cdffb8e50f4ba3f0432c86127 Mon Sep 17 00:00:00 2001 From: SCY Date: Wed, 1 May 2024 15:52:08 +0900 Subject: [PATCH 20/74] =?UTF-8?q?feat(theme):=20=ED=85=8C=EB=A7=88=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C=20API=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: ehbeak --- README.md | 2 +- .../controller/ThemeController.java | 13 ++++++----- .../repository/ReservationTimeDAO.java | 1 - .../java/roomescape/repository/ThemeDAO.java | 6 ++--- .../repository/ThemeRepository.java | 2 +- .../java/roomescape/service/ThemeService.java | 4 ++++ .../controller/ThemeControllerTest.java | 23 +++++++++++++++---- .../roomescape/repository/ThemeDAOTest.java | 7 ++++++ .../service/FakeThemeRepository.java | 9 ++++++-- .../roomescape/service/ThemeServiceTest.java | 10 ++++++-- 10 files changed, 56 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index fee897b943..721c88b2c2 100644 --- a/README.md +++ b/README.md @@ -16,5 +16,5 @@ - [ ] 모든 테마는 시작 시간과 소요 시간이 동일 - [x] 테마 관리 페이지 조회 - [x] 테마 추가 API -- [ ] 테마 삭제 API +- [x] 테마 삭제 API - [x] 테마 조회 API diff --git a/src/main/java/roomescape/controller/ThemeController.java b/src/main/java/roomescape/controller/ThemeController.java index 41bb6990ee..06d67ab6b6 100644 --- a/src/main/java/roomescape/controller/ThemeController.java +++ b/src/main/java/roomescape/controller/ThemeController.java @@ -1,17 +1,12 @@ package roomescape.controller; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import roomescape.controller.request.ThemeRequest; import roomescape.model.Theme; import roomescape.service.ThemeService; -import javax.xml.stream.Location; import java.net.URI; -import java.net.URL; import java.util.List; @RestController @@ -35,4 +30,10 @@ public ResponseEntity addTheme(@RequestBody ThemeRequest themeRequest) { .created(URI.create("/themes/" + theme.getId())) .body(theme); } + + @DeleteMapping("/themes/{id}") + public ResponseEntity deleteTheme(@PathVariable(name = "id") long id) { + themeService.deleteTheme(id); + return ResponseEntity.noContent().build(); + } } diff --git a/src/main/java/roomescape/repository/ReservationTimeDAO.java b/src/main/java/roomescape/repository/ReservationTimeDAO.java index 9c55543199..2115afa3f4 100644 --- a/src/main/java/roomescape/repository/ReservationTimeDAO.java +++ b/src/main/java/roomescape/repository/ReservationTimeDAO.java @@ -56,7 +56,6 @@ public ReservationTime addReservationTime(ReservationTime reservationTime) { public void deleteReservationTime(long id) { String sql = "delete from reservation_time where id = ?"; jdbcTemplate.update(sql, id); - } @Override diff --git a/src/main/java/roomescape/repository/ThemeDAO.java b/src/main/java/roomescape/repository/ThemeDAO.java index 75bfa69bb8..936b1a61ad 100644 --- a/src/main/java/roomescape/repository/ThemeDAO.java +++ b/src/main/java/roomescape/repository/ThemeDAO.java @@ -3,7 +3,6 @@ import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.simple.SimpleJdbcInsert; import org.springframework.stereotype.Repository; -import roomescape.model.ReservationTime; import roomescape.model.Theme; import javax.sql.DataSource; @@ -47,7 +46,8 @@ public Theme addTheme(Theme theme) { } @Override - public long deleteTheme(long id) { - return 0; + public void deleteTheme(long id) { + String sql = "delete from theme where id = ?"; + jdbcTemplate.update(sql, id); } } diff --git a/src/main/java/roomescape/repository/ThemeRepository.java b/src/main/java/roomescape/repository/ThemeRepository.java index e297ae543b..1836616fc7 100644 --- a/src/main/java/roomescape/repository/ThemeRepository.java +++ b/src/main/java/roomescape/repository/ThemeRepository.java @@ -10,5 +10,5 @@ public interface ThemeRepository { Theme addTheme(Theme theme); - long deleteTheme(long id); + void deleteTheme(long id); } diff --git a/src/main/java/roomescape/service/ThemeService.java b/src/main/java/roomescape/service/ThemeService.java index c6c435f4c7..5515dd8493 100644 --- a/src/main/java/roomescape/service/ThemeService.java +++ b/src/main/java/roomescape/service/ThemeService.java @@ -24,4 +24,8 @@ public Theme addTheme(ThemeRequest themeRequest) { Theme theme = new Theme(themeRequest.getName(), themeRequest.getDescription(), themeRequest.getThumbnail()); return themeRepository.addTheme(theme); } + + public void deleteTheme(long id) { + themeRepository.deleteTheme(id); + } } diff --git a/src/test/java/roomescape/controller/ThemeControllerTest.java b/src/test/java/roomescape/controller/ThemeControllerTest.java index 5d9eb70ab9..ca28841484 100644 --- a/src/test/java/roomescape/controller/ThemeControllerTest.java +++ b/src/test/java/roomescape/controller/ThemeControllerTest.java @@ -2,6 +2,7 @@ import io.restassured.RestAssured; import io.restassured.http.ContentType; +import org.assertj.core.api.AssertionsForClassTypes; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -22,9 +23,6 @@ class ThemeControllerTest { @Autowired JdbcTemplate jdbcTemplate; - @Autowired - private ThemeController themeController; - @DisplayName("전체 테마를 조회한다.") @Test void should_get_themes() { @@ -42,7 +40,7 @@ void should_get_themes() { assertThat(themes).hasSize(count); } - @DisplayName("전체 테마를 추가한다.") + @DisplayName("테마를 추가한다.") @Test void should_add_theme() { ThemeRequest request = new ThemeRequest("에버", "공포", "공포.jpg"); @@ -59,4 +57,19 @@ void should_add_theme() { assertThat(count).isEqualTo(1); } -} \ No newline at end of file + + @DisplayName("테마를 삭제한다") + @Test + void should_remove_theme() { + jdbcTemplate.update("INSERT INTO theme (name, description, thumbnail) VALUES (?, ?, ?)", "에버", "공포", "공포.jpg"); + jdbcTemplate.update("INSERT INTO theme (name, description, thumbnail) VALUES (?, ?, ?)", "배키", "미스터리", "미스터리.jpg"); + + RestAssured.given().log().all() + .when().delete("/themes/1") + .then().log().all() + .statusCode(204); + + Integer count = jdbcTemplate.queryForObject("SELECT count(1) from theme", Integer.class); + assertThat(count).isEqualTo(1); + } +} diff --git a/src/test/java/roomescape/repository/ThemeDAOTest.java b/src/test/java/roomescape/repository/ThemeDAOTest.java index 32e43c7f3a..9c3bc5d3cb 100644 --- a/src/test/java/roomescape/repository/ThemeDAOTest.java +++ b/src/test/java/roomescape/repository/ThemeDAOTest.java @@ -68,4 +68,11 @@ void should_add_theme() { themeRepository.addTheme(theme); assertThat(themeRepository.findAllThemes()).hasSize(3); } + + @DisplayName("테마를 삭제한다.") + @Test + void should_delete_theme() { + themeRepository.deleteTheme(1); + assertThat(themeRepository.findAllThemes()).hasSize(1); + } } \ No newline at end of file diff --git a/src/test/java/roomescape/service/FakeThemeRepository.java b/src/test/java/roomescape/service/FakeThemeRepository.java index d1a7d3f0cb..70836364bd 100644 --- a/src/test/java/roomescape/service/FakeThemeRepository.java +++ b/src/test/java/roomescape/service/FakeThemeRepository.java @@ -5,6 +5,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.NoSuchElementException; import java.util.concurrent.atomic.AtomicLong; public class FakeThemeRepository implements ThemeRepository { @@ -30,7 +31,11 @@ public Theme addTheme(Theme theme) { } @Override - public long deleteTheme(long id) { - return 0; + public void deleteTheme(long id) { + Theme targetTheme = themes.stream() + .filter(theme -> theme.getId() == id) + .findFirst() + .orElseThrow(() -> new NoSuchElementException("존재하지 않는 테마입니다.")); + themes.remove(targetTheme); } } diff --git a/src/test/java/roomescape/service/ThemeServiceTest.java b/src/test/java/roomescape/service/ThemeServiceTest.java index 1c5b5c283e..cad80f69bd 100644 --- a/src/test/java/roomescape/service/ThemeServiceTest.java +++ b/src/test/java/roomescape/service/ThemeServiceTest.java @@ -3,7 +3,6 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import roomescape.controller.request.ThemeRequest; -import roomescape.model.Theme; import static org.assertj.core.api.Assertions.*; @@ -21,7 +20,14 @@ void should_find_all_themes() { @Test void should_add_theme() { ThemeRequest themeRequest = new ThemeRequest("에버", "공포", "공포.jpg"); - Theme theme = themeService.addTheme(themeRequest); + themeService.addTheme(themeRequest); assertThat(themeService.findAllThemes()).hasSize(4); } + + @DisplayName("테마를 삭제한다.") + @Test + void should_delete_theme() { + themeService.deleteTheme(1L); + assertThat(themeService.findAllThemes()).hasSize(2); + } } \ No newline at end of file From 50a1e4fb33abaee5227c6b0d4d4aa4a4ae93abcd Mon Sep 17 00:00:00 2001 From: SCY Date: Wed, 1 May 2024 16:30:40 +0900 Subject: [PATCH 21/74] =?UTF-8?q?refactor(reservation):=20=ED=85=8C?= =?UTF-8?q?=EB=A7=88=20=EC=B6=94=EA=B0=80=EC=97=90=20=EB=8B=A4=EB=A5=B8=20?= =?UTF-8?q?=EC=98=88=EC=95=BD=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: ehbeak --- .../request/ReservationRequest.java | 8 ++++- .../java/roomescape/model/Reservation.java | 6 ++-- .../roomescape/repository/ReservationDAO.java | 24 ++++++++++---- .../repository/ReservationRepository.java | 2 +- .../java/roomescape/repository/ThemeDAO.java | 12 +++++++ .../repository/ThemeRepository.java | 2 ++ .../service/ReservationService.java | 18 ++++++++--- .../controller/ReservationControllerTest.java | 8 ++++- .../request/ReservationRequestTest.java | 10 +++--- .../repository/ReservationDAOTest.java | 31 ++++++++++++++++--- .../service/FakeReservationRepository.java | 10 +++--- .../service/FakeThemeRepository.java | 8 +++++ .../service/ReservationServiceTest.java | 14 +++++---- 13 files changed, 117 insertions(+), 36 deletions(-) diff --git a/src/main/java/roomescape/controller/request/ReservationRequest.java b/src/main/java/roomescape/controller/request/ReservationRequest.java index 225878bfaa..5209bdc6b8 100644 --- a/src/main/java/roomescape/controller/request/ReservationRequest.java +++ b/src/main/java/roomescape/controller/request/ReservationRequest.java @@ -10,8 +10,9 @@ public class ReservationRequest { private LocalDate date; private String name; private long timeId; + private long themeId; - public ReservationRequest(String date, String name, long timeId) { + public ReservationRequest(String date, String name, long timeId, long themeId) { validateName(name); validateDate(date); try { @@ -21,6 +22,7 @@ public ReservationRequest(String date, String name, long timeId) { } this.name = name; this.timeId = timeId; + this.themeId = themeId; } private ReservationRequest() { @@ -49,4 +51,8 @@ public String getName() { public long getTimeId() { return timeId; } + + public long getThemeId() { + return themeId; + } } diff --git a/src/main/java/roomescape/model/Reservation.java b/src/main/java/roomescape/model/Reservation.java index 2644d178ff..75d415fe03 100644 --- a/src/main/java/roomescape/model/Reservation.java +++ b/src/main/java/roomescape/model/Reservation.java @@ -13,17 +13,19 @@ public class Reservation { private Reservation() { } - public Reservation(long id, String name, LocalDate date, ReservationTime time) { + public Reservation(long id, String name, LocalDate date, ReservationTime time, Theme theme) { this.id = id; this.name = name; this.date = date; this.time = time; + this.theme = theme; } - public Reservation(String name, LocalDate date, ReservationTime time) { + public Reservation(String name, LocalDate date, ReservationTime time, Theme theme) { this.name = name; this.date = date; this.time = time; + this.theme = theme; } public long getId() { diff --git a/src/main/java/roomescape/repository/ReservationDAO.java b/src/main/java/roomescape/repository/ReservationDAO.java index 16bc8ab2f4..58e82d7df6 100644 --- a/src/main/java/roomescape/repository/ReservationDAO.java +++ b/src/main/java/roomescape/repository/ReservationDAO.java @@ -10,6 +10,7 @@ import org.springframework.stereotype.Repository; import roomescape.model.Reservation; import roomescape.model.ReservationTime; +import roomescape.model.Theme; @Repository public class ReservationDAO implements ReservationRepository { @@ -33,10 +34,14 @@ public List getAllReservations() { r.name, r.date, t.id as time_id, - t.start_at as time_start_at + t.start_at as time_start_at, + th.id as theme_id, + th.name as theme_name, + th.description, + th.thumbnail from reservation as r - inner join reservation_time as t - on r.time_id = t.id + inner join reservation_time as t on r.time_id = t.id + inner join theme as th on r.theme_id = th.id """; return jdbcTemplate.query(sql, (resultSet, rowNum) -> new Reservation( @@ -46,6 +51,12 @@ public List getAllReservations() { new ReservationTime( resultSet.getLong("time_id"), resultSet.getTime("time_start_at").toLocalTime() + ), + new Theme( + resultSet.getLong("theme_id"), + resultSet.getString("theme_name"), + resultSet.getString("description"), + resultSet.getString("thumbnail") ) )); } @@ -56,14 +67,15 @@ public Reservation addReservation(Reservation reservation) { parameters.put("name", reservation.getName()); parameters.put("date", reservation.getDate()); parameters.put("time_id", reservation.getTime().getId()); + parameters.put("theme_id", reservation.getTheme().getId()); Number newId = insertActor.executeAndReturnKey(parameters); - return new Reservation(newId.longValue(), reservation.getName(), reservation.getDate(), reservation.getTime()); + return new Reservation(newId.longValue(), reservation.getName(), reservation.getDate(), reservation.getTime(), reservation.getTheme()); } @Override - public long deleteReservation(long id) { + public void deleteReservation(long id) { String sql = "delete from reservation where id = ?"; - return jdbcTemplate.update(sql, id); + jdbcTemplate.update(sql, id); } @Override diff --git a/src/main/java/roomescape/repository/ReservationRepository.java b/src/main/java/roomescape/repository/ReservationRepository.java index 990be88a2d..60f3bbb8e9 100644 --- a/src/main/java/roomescape/repository/ReservationRepository.java +++ b/src/main/java/roomescape/repository/ReservationRepository.java @@ -9,7 +9,7 @@ public interface ReservationRepository { Reservation addReservation(Reservation reservation); - long deleteReservation(long id); + void deleteReservation(long id); Long countReservationById(long id); diff --git a/src/main/java/roomescape/repository/ThemeDAO.java b/src/main/java/roomescape/repository/ThemeDAO.java index 936b1a61ad..6253d93bbd 100644 --- a/src/main/java/roomescape/repository/ThemeDAO.java +++ b/src/main/java/roomescape/repository/ThemeDAO.java @@ -50,4 +50,16 @@ public void deleteTheme(long id) { String sql = "delete from theme where id = ?"; jdbcTemplate.update(sql, id); } + + @Override + public Theme findThemeById(long id) { + String sql = "select id, name, description, thumbnail from theme where id = ?"; + return jdbcTemplate.queryForObject(sql, (resultSet, ignored) -> + new Theme( + resultSet.getLong("id"), + resultSet.getString("name"), + resultSet.getString("description"), + resultSet.getString("thumbnail") + ), id); + } } diff --git a/src/main/java/roomescape/repository/ThemeRepository.java b/src/main/java/roomescape/repository/ThemeRepository.java index 1836616fc7..211de95bbd 100644 --- a/src/main/java/roomescape/repository/ThemeRepository.java +++ b/src/main/java/roomescape/repository/ThemeRepository.java @@ -11,4 +11,6 @@ public interface ThemeRepository { Theme addTheme(Theme theme); void deleteTheme(long id); + + Theme findThemeById(long id); } diff --git a/src/main/java/roomescape/service/ReservationService.java b/src/main/java/roomescape/service/ReservationService.java index 3f61ad0638..f003ea0aca 100644 --- a/src/main/java/roomescape/service/ReservationService.java +++ b/src/main/java/roomescape/service/ReservationService.java @@ -9,19 +9,24 @@ import roomescape.exception.NotFoundException; import roomescape.model.Reservation; import roomescape.model.ReservationTime; +import roomescape.model.Theme; import roomescape.repository.ReservationRepository; import roomescape.repository.ReservationTimeRepository; +import roomescape.repository.ThemeRepository; @Service public class ReservationService { private final ReservationRepository reservationRepository; - private final ReservationTimeRepository reservationTimeDAO; + private final ReservationTimeRepository reservationTimeRepository; + private final ThemeRepository themeRepository; public ReservationService(ReservationRepository reservationRepository, - ReservationTimeRepository reservationTimeRepository) { + ReservationTimeRepository reservationTimeRepository, + ThemeRepository themeRepository) { this.reservationRepository = reservationRepository; - this.reservationTimeDAO = reservationTimeRepository; + this.reservationTimeRepository = reservationTimeRepository; + this.themeRepository = themeRepository; } public List findAllReservations() { @@ -29,7 +34,9 @@ public List findAllReservations() { } public Reservation addReservation(ReservationRequest request) { - ReservationTime reservationTime = reservationTimeDAO.findReservationById(request.getTimeId()); + ReservationTime reservationTime = reservationTimeRepository.findReservationById(request.getTimeId()); + Theme theme = themeRepository.findThemeById(request.getThemeId()); + LocalDateTime reservationDateTime = LocalDateTime.of(request.getDate(), reservationTime.getStartAt()); if (reservationDateTime.isBefore(LocalDateTime.now())) { throw new BadRequestException("[ERROR] 현재 이전 예약은 할 수 없습니다."); @@ -38,7 +45,8 @@ public Reservation addReservation(ReservationRequest request) { if (countReservation == null || countReservation > 0) { throw new DuplicatedException("[ERROR] 중복되는 예약은 추가할 수 없습니다."); } - return reservationRepository.addReservation(new Reservation(request.getName(), request.getDate(), reservationTime)); + Reservation reservation = new Reservation(request.getName(), request.getDate(), reservationTime, theme); + return reservationRepository.addReservation(reservation); } public void deleteReservation(long id) { diff --git a/src/test/java/roomescape/controller/ReservationControllerTest.java b/src/test/java/roomescape/controller/ReservationControllerTest.java index 86707c3c79..705e546744 100644 --- a/src/test/java/roomescape/controller/ReservationControllerTest.java +++ b/src/test/java/roomescape/controller/ReservationControllerTest.java @@ -28,10 +28,12 @@ class ReservationControllerTest { @Autowired private ReservationController reservationController; + @DisplayName("예약을 조회한다.") @Test void should_get_reservations() { jdbcTemplate.update("INSERT INTO reservation_time (start_at) VALUES (?)", "10:00"); - jdbcTemplate.update("INSERT INTO reservation (name, date, time_id) VALUES (?, ?, ?)", "브라운", "2023-08-05", "1"); + jdbcTemplate.update("INSERT INTO theme (name, description, thumbnail) VALUES (?, ?, ?)", "에버", "공포", "공포.jpg"); + jdbcTemplate.update("INSERT INTO reservation (name, date, time_id, theme_id) VALUES (?, ?, ?, ?)", "브라운", "2030-08-05", "1", "1"); List reservations = RestAssured.given().log().all() .when().get("/reservations") @@ -47,9 +49,13 @@ void should_get_reservations() { @DisplayName("예약을 추가할 수 있다.") @Test void should_insert_reservation() { + jdbcTemplate.update("INSERT INTO reservation_time (start_at) VALUES (?)", "10:00"); + jdbcTemplate.update("INSERT INTO theme (name, description, thumbnail) VALUES (?, ?, ?)", "에버", "공포", "공포.jpg"); + ReservationRequest request = new ReservationRequest( "2030-08-05", "브라운", + 1, 1); RestAssured.given().log().all() diff --git a/src/test/java/roomescape/controller/request/ReservationRequestTest.java b/src/test/java/roomescape/controller/request/ReservationRequestTest.java index 4d78c315fe..58022f19ce 100644 --- a/src/test/java/roomescape/controller/request/ReservationRequestTest.java +++ b/src/test/java/roomescape/controller/request/ReservationRequestTest.java @@ -19,7 +19,7 @@ class ReservationRequestNameTest { @DisplayName("예약자명이 null인 경우 예외를 발생시킨다.") @Test void should_throw_exception_when_name_is_null() { - assertThatThrownBy(() -> new ReservationRequest("2024-04-30", null, 1)) + assertThatThrownBy(() -> new ReservationRequest("2024-04-30", null, 1, 1)) .isInstanceOf(BadRequestException.class) .hasMessage("[ERROR] 유효하지 않은 요청입니다."); } @@ -27,7 +27,7 @@ void should_throw_exception_when_name_is_null() { @DisplayName("예약자명이 빈 문자열인 경우 예외를 발생시킨다.") @Test void should_throw_exception_when_name_is_empty() { - assertThatThrownBy(() -> new ReservationRequest("2024-04-30", "", 1)) + assertThatThrownBy(() -> new ReservationRequest("2024-04-30", "", 1, 1)) .isInstanceOf(BadRequestException.class) .hasMessage("[ERROR] 유효하지 않은 요청입니다."); } @@ -39,7 +39,7 @@ class ReservationRequestDateTest { @DisplayName("날짜가 null인 경우 예외를 발생시킨다.") @Test void should_throw_exception_when_date_is_null() { - assertThatThrownBy(() -> new ReservationRequest(null, "에버", 1)) + assertThatThrownBy(() -> new ReservationRequest(null, "에버", 1, 1)) .isInstanceOf(BadRequestException.class) .hasMessage("[ERROR] 유효하지 않은 요청입니다."); } @@ -47,7 +47,7 @@ void should_throw_exception_when_date_is_null() { @DisplayName("날짜가 비어있는 경우 예외를 발생시킨다.") @Test void should_throw_exception_when_date_is_empty() { - assertThatThrownBy(() -> new ReservationRequest("", "배키", 1)) + assertThatThrownBy(() -> new ReservationRequest("", "배키", 1, 1)) .isInstanceOf(BadRequestException.class) .hasMessage("[ERROR] 유효하지 않은 요청입니다."); } @@ -56,7 +56,7 @@ void should_throw_exception_when_date_is_empty() { @ParameterizedTest @ValueSource(strings = {"2024:03:27", "2024/01/11", "에베", "12-12"}) void should_throw_exception_when_date_is_bad_format(String date) { - assertThatThrownBy(() -> new ReservationRequest(date, "배키", 1)) + assertThatThrownBy(() -> new ReservationRequest(date, "배키", 1, 1)) .isInstanceOf(BadRequestException.class) .hasMessage("[ERROR] 유효하지 않은 요청입니다."); } diff --git a/src/test/java/roomescape/repository/ReservationDAOTest.java b/src/test/java/roomescape/repository/ReservationDAOTest.java index a7336e66f2..08f156d770 100644 --- a/src/test/java/roomescape/repository/ReservationDAOTest.java +++ b/src/test/java/roomescape/repository/ReservationDAOTest.java @@ -18,6 +18,7 @@ import org.springframework.test.annotation.DirtiesContext; import roomescape.model.Reservation; import roomescape.model.ReservationTime; +import roomescape.model.Theme; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) @@ -36,6 +37,8 @@ class ReservationDAOTest { SimpleJdbcInsert reservationInsertActor; + SimpleJdbcInsert themeInsertActor; + @BeforeEach void setUp() { jdbcTemplate.execute("TRUNCATE TABLE reservation RESTART IDENTITY"); @@ -49,12 +52,18 @@ void setUp() { reservationInsertActor = new SimpleJdbcInsert(dataSource) .withTableName("reservation") .usingGeneratedKeyColumns("id"); + themeInsertActor = new SimpleJdbcInsert(dataSource) + .withTableName("theme") + .usingGeneratedKeyColumns("id"); insertReservationTime("10:00"); insertReservationTime("11:00"); - insertToReservation("브라운", "2023-08-05", "1"); - insertToReservation("리사", "2023-08-01", "2"); + insertTheme("에버", "공포", "공포.jpg"); + insertTheme("배키", "스릴러", "스릴러.jpg"); + + insertReservation("브라운", "2023-08-05", "1", "1"); + insertReservation("리사", "2023-08-01", "2", "2"); } private void insertReservationTime(String startAt) { @@ -63,14 +72,23 @@ private void insertReservationTime(String startAt) { reservationTimeInsertActor.execute(parameters); } - private void insertToReservation(String name, String date, String timeId) { + private void insertReservation(String name, String date, String timeId, String themeId) { Map parameters = new HashMap<>(3); parameters.put("name", name); parameters.put("date", date); parameters.put("time_id", timeId); + parameters.put("theme_id", themeId); reservationInsertActor.execute(parameters); } + private void insertTheme(String name, String description, String thumbnail) { + Map parameters = new HashMap<>(3); + parameters.put("name", name); + parameters.put("description", description); + parameters.put("thumbnail", thumbnail); + themeInsertActor.execute(parameters); + } + @DisplayName("모든 예약을 조회한다") @Test void should_get_reservation() { @@ -89,8 +107,11 @@ void should_get_reservation_times() { @Test void should_add_reservation() { ReservationTime reservationTime = new ReservationTime(1, LocalTime.of(10, 0)); - reservationRepository.addReservation( - new Reservation("네오", LocalDate.of(2024, 9, 1), reservationTime)); + Theme theme = new Theme(1, "에버", "공포", "공포.jpg"); + Reservation reservation = new Reservation("네오", LocalDate.of(2024, 9, 1), reservationTime, theme); + + reservationRepository.addReservation(reservation); + Integer count = jdbcTemplate.queryForObject("select count(1) from reservation", Integer.class); assertThat(count).isEqualTo(3); } diff --git a/src/test/java/roomescape/service/FakeReservationRepository.java b/src/test/java/roomescape/service/FakeReservationRepository.java index 99cf92fda1..aa4da376ce 100644 --- a/src/test/java/roomescape/service/FakeReservationRepository.java +++ b/src/test/java/roomescape/service/FakeReservationRepository.java @@ -2,6 +2,7 @@ import roomescape.model.Reservation; import roomescape.model.ReservationTime; +import roomescape.model.Theme; import roomescape.repository.ReservationRepository; import java.time.LocalDate; @@ -14,9 +15,11 @@ class FakeReservationRepository implements ReservationRepository { private List reservations = new ArrayList<>(List.of( new Reservation(1, "브라운", LocalDate.of(2030, 8, 5), - new ReservationTime(2, LocalTime.of(11, 0))), + new ReservationTime(2, LocalTime.of(11, 0)), + new Theme(1, "에버", "공포", "공포.jpg")), new Reservation(1, "리사", LocalDate.of(2030, 8, 1), - new ReservationTime(2, LocalTime.of(11, 0))))); + new ReservationTime(2, LocalTime.of(11, 0)), + new Theme(2, "배키", "스릴러", "스릴러.jpg")))); @Override public List getAllReservations() { @@ -30,13 +33,12 @@ public Reservation addReservation(Reservation reservation) { } @Override - public long deleteReservation(long id) { + public void deleteReservation(long id) { Reservation foundReservation = reservations.stream() .filter(reservation -> reservation.getId() == id) .findFirst() .orElseThrow(() -> new NoSuchElementException("아이디가 존재하지 않습니다.")); reservations.remove(foundReservation); - return id; } @Override diff --git a/src/test/java/roomescape/service/FakeThemeRepository.java b/src/test/java/roomescape/service/FakeThemeRepository.java index 70836364bd..08a2e4fe30 100644 --- a/src/test/java/roomescape/service/FakeThemeRepository.java +++ b/src/test/java/roomescape/service/FakeThemeRepository.java @@ -38,4 +38,12 @@ public void deleteTheme(long id) { .orElseThrow(() -> new NoSuchElementException("존재하지 않는 테마입니다.")); themes.remove(targetTheme); } + + @Override + public Theme findThemeById(long id) { + return themes.stream() + .filter(theme -> theme.getId() == id) + .findFirst() + .orElseThrow(() -> new NoSuchElementException("존재하지 않는 테마입니다.")); + } } diff --git a/src/test/java/roomescape/service/ReservationServiceTest.java b/src/test/java/roomescape/service/ReservationServiceTest.java index ef8e049e2e..54e6c40b05 100644 --- a/src/test/java/roomescape/service/ReservationServiceTest.java +++ b/src/test/java/roomescape/service/ReservationServiceTest.java @@ -14,8 +14,10 @@ import static org.assertj.core.api.Assertions.*; class ReservationServiceTest { - ReservationService reservationService = new ReservationService(new FakeReservationRepository(), - new FakeReservationTimeRepository()); + ReservationService reservationService = new ReservationService( + new FakeReservationRepository(), + new FakeReservationTimeRepository(), + new FakeThemeRepository()); @DisplayName("모든 예약 시간을 반환한다") @Test @@ -28,7 +30,7 @@ void should_return_all_reservation_times() { @Test void should_add_reservation_times() { reservationService.addReservation( - new ReservationRequest("2030-01-01", "네오", 1)); + new ReservationRequest("2030-01-01", "네오", 1, 1)); List allReservations = reservationService.findAllReservations(); assertThat(allReservations).hasSize(3); } @@ -60,7 +62,7 @@ void should_not_throw_exception_when_exist_reservation_time() { @DisplayName("현재 이전으로 예약하면 예외가 발생한다.") @Test void should_throw_exception_when_previous_date() { - ReservationRequest request = new ReservationRequest("2000-01-11", "에버", 1); + ReservationRequest request = new ReservationRequest("2000-01-11", "에버", 1, 1); assertThatThrownBy(() -> reservationService.addReservation(request)) .isInstanceOf(BadRequestException.class) .hasMessage("[ERROR] 현재 이전 예약은 할 수 없습니다."); @@ -69,7 +71,7 @@ void should_throw_exception_when_previous_date() { @DisplayName("현재 이후로 예약하면 예외가 발생하지 않는다.") @Test void should_not_throw_exception_when_later_date() { - ReservationRequest request = new ReservationRequest("2030-01-11", "에버", 1); + ReservationRequest request = new ReservationRequest("2030-01-11", "에버", 1, 1); assertThatCode(() -> reservationService.addReservation(request)) .doesNotThrowAnyException(); } @@ -77,7 +79,7 @@ void should_not_throw_exception_when_later_date() { @DisplayName("날짜, 시간이 일치하는 예약을 추가하려 할 때 예외가 발생한다.") @Test void should_throw_exception_when_add_exist_reservation() { - ReservationRequest request = new ReservationRequest("2030-08-05", "배키", 2); + ReservationRequest request = new ReservationRequest("2030-08-05", "배키", 2, 2); assertThatThrownBy(() -> reservationService.addReservation(request)) .isInstanceOf(DuplicatedException.class) .hasMessage("[ERROR] 중복되는 예약은 추가할 수 없습니다."); From 1be9f4f94079f5ce31efd54397cfde23845554ae Mon Sep 17 00:00:00 2001 From: SCY Date: Wed, 1 May 2024 17:05:56 +0900 Subject: [PATCH 22/74] =?UTF-8?q?docs(README):=203=EB=8B=A8=EA=B3=84=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EC=9A=94=EA=B5=AC=EC=82=AC=ED=95=AD=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: ehbeak --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 721c88b2c2..ee8b94f330 100644 --- a/README.md +++ b/README.md @@ -18,3 +18,11 @@ - [x] 테마 추가 API - [x] 테마 삭제 API - [x] 테마 조회 API + +- [ ] (관리자가 아닌) 사용자가 예약 가능한 시간을 조회하고, 예약할 수 있도록 기능을 추가/변경 + - [ ] 테마와 날짜를 선택하면 예약 가능한 시간 조회 + - [ ] 예약 추가 + - [ ] /reservation 요청 시 사용자 예약 페이지 조회 +- [ ] 인기 테마 조회 기능을 추가 + - [ ] 최근 일주일을 기준으로 하여 해당 기간 내에 방문하는 예약이 많은 테마 10개를 확인 + - [ ] / 요청 시 인기 테마 페이지 조회 \ No newline at end of file From 76afbf32b811ace06bd18374a7bae0d0b9aff922 Mon Sep 17 00:00:00 2001 From: SCY Date: Wed, 1 May 2024 17:10:25 +0900 Subject: [PATCH 23/74] =?UTF-8?q?feat(StaticUserPageController):=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=EC=9E=90=20=EC=98=88=EC=95=BD=20=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20=EC=A1=B0=ED=9A=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: ehbeak --- README.md | 2 +- ...ntroller.java => StaticAdminPageController.java} | 2 +- .../controller/StaticUserPageController.java | 13 +++++++++++++ 3 files changed, 15 insertions(+), 2 deletions(-) rename src/main/java/roomescape/controller/{StaticPageController.java => StaticAdminPageController.java} (93%) create mode 100644 src/main/java/roomescape/controller/StaticUserPageController.java diff --git a/README.md b/README.md index ee8b94f330..3c58b6802f 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ - [ ] (관리자가 아닌) 사용자가 예약 가능한 시간을 조회하고, 예약할 수 있도록 기능을 추가/변경 - [ ] 테마와 날짜를 선택하면 예약 가능한 시간 조회 - [ ] 예약 추가 - - [ ] /reservation 요청 시 사용자 예약 페이지 조회 + - [X] /reservation 요청 시 사용자 예약 페이지 조회 - [ ] 인기 테마 조회 기능을 추가 - [ ] 최근 일주일을 기준으로 하여 해당 기간 내에 방문하는 예약이 많은 테마 10개를 확인 - [ ] / 요청 시 인기 테마 페이지 조회 \ No newline at end of file diff --git a/src/main/java/roomescape/controller/StaticPageController.java b/src/main/java/roomescape/controller/StaticAdminPageController.java similarity index 93% rename from src/main/java/roomescape/controller/StaticPageController.java rename to src/main/java/roomescape/controller/StaticAdminPageController.java index 85b4742994..a8d2ff8530 100644 --- a/src/main/java/roomescape/controller/StaticPageController.java +++ b/src/main/java/roomescape/controller/StaticAdminPageController.java @@ -4,7 +4,7 @@ import org.springframework.web.bind.annotation.GetMapping; @Controller -public class StaticPageController { +public class StaticAdminPageController { @GetMapping(path = {"/", "/admin"}) public String getAdminPage() { return "admin/index"; diff --git a/src/main/java/roomescape/controller/StaticUserPageController.java b/src/main/java/roomescape/controller/StaticUserPageController.java new file mode 100644 index 0000000000..5ef93a6a7f --- /dev/null +++ b/src/main/java/roomescape/controller/StaticUserPageController.java @@ -0,0 +1,13 @@ +package roomescape.controller; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; + +@Controller +public class StaticUserPageController { + + @GetMapping("/reservation") + public String getReservation() { + return "reservation"; + } +} From ac47daa9b7a7910d732c6a10e848fa71a7b67640 Mon Sep 17 00:00:00 2001 From: SCY Date: Wed, 1 May 2024 17:14:46 +0900 Subject: [PATCH 24/74] =?UTF-8?q?fix(js):=20=ED=85=8C=EB=A7=88=20=EB=AA=A9?= =?UTF-8?q?=EB=A1=9D=20=EC=A1=B0=ED=9A=8C=20=ED=9B=84=20=EB=A0=8C=EB=8D=94?= =?UTF-8?q?=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: ehbeak --- src/main/resources/static/js/user-reservation.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/resources/static/js/user-reservation.js b/src/main/resources/static/js/user-reservation.js index 89ff141af8..a5da71b06e 100644 --- a/src/main/resources/static/js/user-reservation.js +++ b/src/main/resources/static/js/user-reservation.js @@ -36,9 +36,9 @@ function renderTheme(themes) { const themeSlots = document.getElementById('theme-slots'); themeSlots.innerHTML = ''; themes.forEach(theme => { - const name = ''; - const themeId = ''; - /* + const name = theme.name; + const themeId = theme.themeId; + /* 완료! TODO: [3단계] 사용자 예약 - 테마 목록 조회 API 호출 후 렌더링 response 명세에 맞춰 createSlot 함수 호출 시 값 설정 createSlot('theme', theme name, theme id) 형태로 호출 From 1d5fe56cf8a14ff8794ed82b5edae38e9cb06618 Mon Sep 17 00:00:00 2001 From: SCY Date: Wed, 1 May 2024 21:04:06 +0900 Subject: [PATCH 25/74] =?UTF-8?q?feat(Reservation):=20=ED=85=8C=EB=A7=88?= =?UTF-8?q?=EC=99=80=20=EB=82=A0=EC=A7=9C=EB=A5=BC=20=EC=84=A0=ED=83=9D?= =?UTF-8?q?=ED=95=98=EB=A9=B4=20=EC=98=88=EC=95=BD=20=EA=B0=80=EB=8A=A5?= =?UTF-8?q?=ED=95=9C=20=EC=8B=9C=EA=B0=84=20=EC=A1=B0=ED=9A=8C=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: ehbeak --- README.md | 6 ++-- .../controller/ReservationController.java | 18 +++++++---- .../controller/ThemeController.java | 2 +- .../MemberReservationTimeResponse.java | 32 +++++++++++++++++++ src/main/java/roomescape/model/Theme.java | 10 +++--- .../roomescape/repository/ReservationDAO.java | 16 +++++++++- .../repository/ReservationRepository.java | 3 ++ .../service/ReservationService.java | 23 +++++++++++++ src/main/resources/schema.sql | 2 ++ .../resources/static/js/user-reservation.js | 12 +++---- .../service/FakeReservationRepository.java | 8 +++++ .../service/FakeThemeRepository.java | 4 +-- 12 files changed, 112 insertions(+), 24 deletions(-) create mode 100644 src/main/java/roomescape/controller/response/MemberReservationTimeResponse.java diff --git a/README.md b/README.md index 3c58b6802f..e1b2008d3a 100644 --- a/README.md +++ b/README.md @@ -19,9 +19,9 @@ - [x] 테마 삭제 API - [x] 테마 조회 API -- [ ] (관리자가 아닌) 사용자가 예약 가능한 시간을 조회하고, 예약할 수 있도록 기능을 추가/변경 - - [ ] 테마와 날짜를 선택하면 예약 가능한 시간 조회 - - [ ] 예약 추가 +- [x] (관리자가 아닌) 사용자가 예약 가능한 시간을 조회하고, 예약할 수 있도록 기능을 추가/변경 + - [x] 테마와 날짜를 선택하면 예약 가능한 시간 조회 + - [x] 예약 추가 - [X] /reservation 요청 시 사용자 예약 페이지 조회 - [ ] 인기 테마 조회 기능을 추가 - [ ] 최근 일주일을 기준으로 하여 해당 기간 내에 방문하는 예약이 많은 테마 10개를 확인 diff --git a/src/main/java/roomescape/controller/ReservationController.java b/src/main/java/roomescape/controller/ReservationController.java index 4afcff4755..f2678cf608 100644 --- a/src/main/java/roomescape/controller/ReservationController.java +++ b/src/main/java/roomescape/controller/ReservationController.java @@ -1,16 +1,14 @@ package roomescape.controller; import java.net.URI; +import java.time.LocalDate; import java.util.List; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import roomescape.controller.request.ReservationRequest; +import roomescape.controller.response.MemberReservationTimeResponse; import roomescape.model.Reservation; +import roomescape.model.ReservationTime; import roomescape.service.ReservationService; @RestController @@ -38,4 +36,12 @@ public ResponseEntity deleteReservation(@PathVariable("id") long id) { reservationService.deleteReservation(id); return ResponseEntity.noContent().build(); } + + @GetMapping("/reservations/times") + public ResponseEntity> getPossibleReservationTimes( + @RequestParam(name = "date") LocalDate date, + @RequestParam(name = "themeId") long themeId) { + List response = reservationService.getMemberReservationTimes(date, themeId); + return ResponseEntity.ok(response); + } } diff --git a/src/main/java/roomescape/controller/ThemeController.java b/src/main/java/roomescape/controller/ThemeController.java index 06d67ab6b6..e277a170f6 100644 --- a/src/main/java/roomescape/controller/ThemeController.java +++ b/src/main/java/roomescape/controller/ThemeController.java @@ -27,7 +27,7 @@ public ResponseEntity> getThemes() { public ResponseEntity addTheme(@RequestBody ThemeRequest themeRequest) { Theme theme = themeService.addTheme(themeRequest); return ResponseEntity - .created(URI.create("/themes/" + theme.getId())) + .created(URI.create("/themes/" + theme.getThemeId())) .body(theme); } diff --git a/src/main/java/roomescape/controller/response/MemberReservationTimeResponse.java b/src/main/java/roomescape/controller/response/MemberReservationTimeResponse.java new file mode 100644 index 0000000000..7825573646 --- /dev/null +++ b/src/main/java/roomescape/controller/response/MemberReservationTimeResponse.java @@ -0,0 +1,32 @@ +package roomescape.controller.response; + +import java.time.LocalTime; + +public class MemberReservationTimeResponse { + + private final long timeId; + private final LocalTime startAt; + private boolean alreadyBooked; + + public MemberReservationTimeResponse(long timeId, LocalTime startAt, boolean alreadyBooked) { + this.timeId = timeId; + this.startAt = startAt; + this.alreadyBooked = alreadyBooked; + } + + public void setAlreadyBooked(boolean alreadyBooked) { + this.alreadyBooked = alreadyBooked; + } + + public long getTimeId() { + return timeId; + } + + public LocalTime getStartAt() { + return startAt; + } + + public boolean getAlreadyBooked() { + return alreadyBooked; + } +} diff --git a/src/main/java/roomescape/model/Theme.java b/src/main/java/roomescape/model/Theme.java index 295b5f42b2..18ff597dc0 100644 --- a/src/main/java/roomescape/model/Theme.java +++ b/src/main/java/roomescape/model/Theme.java @@ -2,7 +2,7 @@ public class Theme { - private long id; + private long themeId; private String name; private String description; private String thumbnail; @@ -10,8 +10,8 @@ public class Theme { private Theme() { } - public Theme(long id, String name, String description, String thumbnail) { - this.id = id; + public Theme(long themeId, String name, String description, String thumbnail) { + this.themeId = themeId; this.name = name; this.description = description; this.thumbnail = thumbnail; @@ -23,8 +23,8 @@ public Theme(String name, String description, String thumbnail) { this.thumbnail = thumbnail; } - public long getId() { - return id; + public long getThemeId() { + return themeId; } public String getName() { diff --git a/src/main/java/roomescape/repository/ReservationDAO.java b/src/main/java/roomescape/repository/ReservationDAO.java index 58e82d7df6..b87c888260 100644 --- a/src/main/java/roomescape/repository/ReservationDAO.java +++ b/src/main/java/roomescape/repository/ReservationDAO.java @@ -67,7 +67,7 @@ public Reservation addReservation(Reservation reservation) { parameters.put("name", reservation.getName()); parameters.put("date", reservation.getDate()); parameters.put("time_id", reservation.getTime().getId()); - parameters.put("theme_id", reservation.getTheme().getId()); + parameters.put("theme_id", reservation.getTheme().getThemeId()); Number newId = insertActor.executeAndReturnKey(parameters); return new Reservation(newId.longValue(), reservation.getName(), reservation.getDate(), reservation.getTime(), reservation.getTheme()); } @@ -95,4 +95,18 @@ public Long countReservationByDateAndTimeId(LocalDate date, long timeId) { String sql = "select count(id) from reservation where date = ? and time_id = ?"; return jdbcTemplate.queryForObject(sql, (resultSet, ignored) -> resultSet.getLong(1), date, timeId); } + + @Override + public List findReservationTimeByDateAndTheme(LocalDate date, long themeId) { + String sql = """ + select t.id as time_id, t.start_at as start_at + from reservation as r inner join reservation_time as t on r.time_id = t.id + where date = ? and theme_id = ? + """; + return jdbcTemplate.query(sql, (resultSet, rowNum) -> + new ReservationTime( + resultSet.getLong("time_id"), + resultSet.getTime("start_at").toLocalTime() + ), date, themeId); + } } diff --git a/src/main/java/roomescape/repository/ReservationRepository.java b/src/main/java/roomescape/repository/ReservationRepository.java index 60f3bbb8e9..7db25e4c25 100644 --- a/src/main/java/roomescape/repository/ReservationRepository.java +++ b/src/main/java/roomescape/repository/ReservationRepository.java @@ -3,6 +3,7 @@ import java.time.LocalDate; import java.util.List; import roomescape.model.Reservation; +import roomescape.model.ReservationTime; public interface ReservationRepository { List getAllReservations(); @@ -16,4 +17,6 @@ public interface ReservationRepository { Long countReservationByTimeId(long timeId); Long countReservationByDateAndTimeId(LocalDate date, long timeId); + + List findReservationTimeByDateAndTheme(LocalDate date, long themeId); } diff --git a/src/main/java/roomescape/service/ReservationService.java b/src/main/java/roomescape/service/ReservationService.java index f003ea0aca..341ba7d7e5 100644 --- a/src/main/java/roomescape/service/ReservationService.java +++ b/src/main/java/roomescape/service/ReservationService.java @@ -1,9 +1,11 @@ package roomescape.service; +import java.time.LocalDate; import java.time.LocalDateTime; import java.util.List; import org.springframework.stereotype.Service; import roomescape.controller.request.ReservationRequest; +import roomescape.controller.response.MemberReservationTimeResponse; import roomescape.exception.BadRequestException; import roomescape.exception.DuplicatedException; import roomescape.exception.NotFoundException; @@ -56,4 +58,25 @@ public void deleteReservation(long id) { } reservationRepository.deleteReservation(id); } + + public List getMemberReservationTimes(LocalDate date, long themeId) { + List allTimes = reservationTimeRepository.findAllReservationTimes(); + + List alreadyBookedTimes = reservationRepository.findReservationTimeByDateAndTheme(date, themeId); + + List responses = allTimes.stream() + .map(time -> new MemberReservationTimeResponse(time.getId(), time.getStartAt(), false)) + .toList(); + + for (MemberReservationTimeResponse response : responses) { + for (ReservationTime alreadyBookedTime : alreadyBookedTimes) { + if (response.getTimeId() == alreadyBookedTime.getId()) { + response.setAlreadyBooked(true); + } + } + } + // TODO: 리팩토링 + + return responses; + } } diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql index e5c82b2155..875e0aa2f4 100644 --- a/src/main/resources/schema.sql +++ b/src/main/resources/schema.sql @@ -29,3 +29,5 @@ CREATE TABLE reservation INSERT INTO reservation_time (start_at) VALUES ('10:00'); INSERT INTO reservation_time (start_at) VALUES ('11:00'); +INSERT INTO theme (name, description, thumbnail) VALUES ('에버', '공포', '공포.jpg'); +INSERT INTO theme (name, description, thumbnail) VALUES ('배키', '스릴러', '스릴러.jpg'); \ No newline at end of file diff --git a/src/main/resources/static/js/user-reservation.js b/src/main/resources/static/js/user-reservation.js index a5da71b06e..b5454103e9 100644 --- a/src/main/resources/static/js/user-reservation.js +++ b/src/main/resources/static/js/user-reservation.js @@ -38,8 +38,8 @@ function renderTheme(themes) { themes.forEach(theme => { const name = theme.name; const themeId = theme.themeId; - /* 완료! - TODO: [3단계] 사용자 예약 - 테마 목록 조회 API 호출 후 렌더링 + /* + TODO: 완료 [3단계] 사용자 예약 - 테마 목록 조회 API 호출 후 렌더링 response 명세에 맞춰 createSlot 함수 호출 시 값 설정 createSlot('theme', theme name, theme id) 형태로 호출 */ @@ -91,7 +91,7 @@ function fetchAvailableTimes(date, themeId) { TODO: [3단계] 사용자 예약 - 예약 가능 시간 조회 API 호출 요청 포맷에 맞게 설정 */ - fetch('/', { // 예약 가능 시간 조회 API endpoint + fetch('/reservations/times?date=' + date + '&themeId=' + themeId, { // 예약 가능 시간 조회 API endpoint method: 'GET', headers: { 'Content-Type': 'application/json', @@ -120,9 +120,9 @@ function renderAvailableTimes(times) { TODO: [3단계] 사용자 예약 - 예약 가능 시간 조회 API 호출 후 렌더링 response 명세에 맞춰 createSlot 함수 호출 시 값 설정 */ - const startAt = ''; - const timeId = ''; - const alreadyBooked = false; + const startAt = time.startAt; + const timeId = time.timeId; + const alreadyBooked = time.alreadyBooked; const div = createSlot('time', startAt, timeId, alreadyBooked); // createSlot('time', 시작 시간, time id, 예약 여부) timeSlots.appendChild(div); diff --git a/src/test/java/roomescape/service/FakeReservationRepository.java b/src/test/java/roomescape/service/FakeReservationRepository.java index aa4da376ce..02ec7f96f8 100644 --- a/src/test/java/roomescape/service/FakeReservationRepository.java +++ b/src/test/java/roomescape/service/FakeReservationRepository.java @@ -62,4 +62,12 @@ public Long countReservationByDateAndTimeId(LocalDate date, long timeId) { && reservation.getTime().getId() == timeId) .count(); } + + @Override + public List findReservationTimeByDateAndTheme(LocalDate date, long themeId) { + return reservations.stream() + .filter(reservation -> reservation.getDate() == date && reservation.getTheme().getThemeId() == themeId) + .map(reservation -> new ReservationTime(reservation.getId(), reservation.getTime().getStartAt())) + .toList(); + } } \ No newline at end of file diff --git a/src/test/java/roomescape/service/FakeThemeRepository.java b/src/test/java/roomescape/service/FakeThemeRepository.java index 08a2e4fe30..7ddc00de23 100644 --- a/src/test/java/roomescape/service/FakeThemeRepository.java +++ b/src/test/java/roomescape/service/FakeThemeRepository.java @@ -33,7 +33,7 @@ public Theme addTheme(Theme theme) { @Override public void deleteTheme(long id) { Theme targetTheme = themes.stream() - .filter(theme -> theme.getId() == id) + .filter(theme -> theme.getThemeId() == id) .findFirst() .orElseThrow(() -> new NoSuchElementException("존재하지 않는 테마입니다.")); themes.remove(targetTheme); @@ -42,7 +42,7 @@ public void deleteTheme(long id) { @Override public Theme findThemeById(long id) { return themes.stream() - .filter(theme -> theme.getId() == id) + .filter(theme -> theme.getThemeId() == id) .findFirst() .orElseThrow(() -> new NoSuchElementException("존재하지 않는 테마입니다.")); } From b29334fae5da3a12e1897f21ca7935b9386664e8 Mon Sep 17 00:00:00 2001 From: SCY Date: Thu, 2 May 2024 10:42:10 +0900 Subject: [PATCH 26/74] =?UTF-8?q?feat(StaticUserPageController):=20?= =?UTF-8?q?=EC=9D=B8=EA=B8=B0=20=ED=85=8C=EB=A7=88=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20=EC=A1=B0=ED=9A=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: ehbeak --- README.md | 2 +- .../roomescape/controller/StaticAdminPageController.java | 2 +- .../java/roomescape/controller/StaticUserPageController.java | 5 +++++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e1b2008d3a..bab6c4dd00 100644 --- a/README.md +++ b/README.md @@ -25,4 +25,4 @@ - [X] /reservation 요청 시 사용자 예약 페이지 조회 - [ ] 인기 테마 조회 기능을 추가 - [ ] 최근 일주일을 기준으로 하여 해당 기간 내에 방문하는 예약이 많은 테마 10개를 확인 - - [ ] / 요청 시 인기 테마 페이지 조회 \ No newline at end of file + - [x] / 요청 시 인기 테마 페이지 조회 \ No newline at end of file diff --git a/src/main/java/roomescape/controller/StaticAdminPageController.java b/src/main/java/roomescape/controller/StaticAdminPageController.java index a8d2ff8530..450a624927 100644 --- a/src/main/java/roomescape/controller/StaticAdminPageController.java +++ b/src/main/java/roomescape/controller/StaticAdminPageController.java @@ -5,7 +5,7 @@ @Controller public class StaticAdminPageController { - @GetMapping(path = {"/", "/admin"}) + @GetMapping("/admin") public String getAdminPage() { return "admin/index"; } diff --git a/src/main/java/roomescape/controller/StaticUserPageController.java b/src/main/java/roomescape/controller/StaticUserPageController.java index 5ef93a6a7f..cebbcff2eb 100644 --- a/src/main/java/roomescape/controller/StaticUserPageController.java +++ b/src/main/java/roomescape/controller/StaticUserPageController.java @@ -6,6 +6,11 @@ @Controller public class StaticUserPageController { + @GetMapping("/") + public String getHome() { + return "index"; + } + @GetMapping("/reservation") public String getReservation() { return "reservation"; From 1bcbf533b3a719a3f4a1855f298ee9e16030fb87 Mon Sep 17 00:00:00 2001 From: SCY Date: Thu, 2 May 2024 13:13:29 +0900 Subject: [PATCH 27/74] =?UTF-8?q?feat(theme):=20=EC=9D=B8=EA=B8=B0=20?= =?UTF-8?q?=ED=85=8C=EB=A7=88=20=EC=A1=B0=ED=9A=8C=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: ehbeak --- README.md | 6 +- .../controller/ThemeController.java | 5 + src/main/java/roomescape/model/Theme.java | 25 +++++ .../java/roomescape/repository/ThemeDAO.java | 21 ++++ .../repository/ThemeRepository.java | 3 + .../java/roomescape/service/ThemeService.java | 8 ++ src/main/resources/schema.sql | 4 +- src/main/resources/static/js/ranking.js | 10 +- .../resources/static/js/user-reservation.js | 4 +- .../controller/ThemeControllerTest.java | 101 +++++++++++++++++- .../roomescape/repository/ThemeDAOTest.java | 66 +++++++++++- .../service/FakeThemeRepository.java | 19 ++++ .../roomescape/service/ThemeServiceTest.java | 22 ++++ 13 files changed, 275 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index bab6c4dd00..2f333db433 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ - [x] 예약 시간 중복 불가능 - [x] '테마' 도메인 추가 - - [ ] 모든 테마는 시작 시간과 소요 시간이 동일 + - [x] 모든 테마는 시작 시간과 소요 시간이 동일 - [x] 테마 관리 페이지 조회 - [x] 테마 추가 API - [x] 테마 삭제 API @@ -23,6 +23,6 @@ - [x] 테마와 날짜를 선택하면 예약 가능한 시간 조회 - [x] 예약 추가 - [X] /reservation 요청 시 사용자 예약 페이지 조회 -- [ ] 인기 테마 조회 기능을 추가 - - [ ] 최근 일주일을 기준으로 하여 해당 기간 내에 방문하는 예약이 많은 테마 10개를 확인 +- [x] 인기 테마 조회 기능을 추가 + - [x] 최근 일주일을 기준으로 하여 해당 기간 내에 방문하는 예약이 많은 테마 10개를 확인 - [x] / 요청 시 인기 테마 페이지 조회 \ No newline at end of file diff --git a/src/main/java/roomescape/controller/ThemeController.java b/src/main/java/roomescape/controller/ThemeController.java index e277a170f6..0983a533dc 100644 --- a/src/main/java/roomescape/controller/ThemeController.java +++ b/src/main/java/roomescape/controller/ThemeController.java @@ -36,4 +36,9 @@ public ResponseEntity deleteTheme(@PathVariable(name = "id") long id) { themeService.deleteTheme(id); return ResponseEntity.noContent().build(); } + + @GetMapping("/themes/rank") + public ResponseEntity> getPopularThemes() { + return ResponseEntity.ok(themeService.findPopularThemes()); + } } diff --git a/src/main/java/roomescape/model/Theme.java b/src/main/java/roomescape/model/Theme.java index 18ff597dc0..2f624d620d 100644 --- a/src/main/java/roomescape/model/Theme.java +++ b/src/main/java/roomescape/model/Theme.java @@ -1,5 +1,7 @@ package roomescape.model; +import java.util.Objects; + public class Theme { private long themeId; @@ -38,4 +40,27 @@ public String getDescription() { public String getThumbnail() { return thumbnail; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Theme theme = (Theme) o; + return themeId == theme.themeId && Objects.equals(name, theme.name) && Objects.equals(description, theme.description) && Objects.equals(thumbnail, theme.thumbnail); + } + + @Override + public int hashCode() { + return Objects.hash(themeId, name, description, thumbnail); + } + + @Override + public String toString() { + return "Theme{" + + "themeId=" + themeId + + ", name='" + name + '\'' + + ", description='" + description + '\'' + + ", thumbnail='" + thumbnail + '\'' + + '}'; + } } diff --git a/src/main/java/roomescape/repository/ThemeDAO.java b/src/main/java/roomescape/repository/ThemeDAO.java index 6253d93bbd..809f3051a3 100644 --- a/src/main/java/roomescape/repository/ThemeDAO.java +++ b/src/main/java/roomescape/repository/ThemeDAO.java @@ -6,6 +6,7 @@ import roomescape.model.Theme; import javax.sql.DataSource; +import java.time.LocalDate; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -62,4 +63,24 @@ public Theme findThemeById(long id) { resultSet.getString("thumbnail") ), id); } + + @Override + public List findThemeRankingByDate(LocalDate before, LocalDate after, int limit) { + String sql = """ + select th.id, th.name, th.description, th.thumbnail + from reservation as r + inner join theme as th on r.theme_id = th.id + where r.date between ? and ? + group by r.theme_id + order by count(r.theme_id) desc + limit ? + """; + return jdbcTemplate.query(sql, (resultSet, ignored) -> + new Theme( + resultSet.getLong("id"), + resultSet.getString("name"), + resultSet.getString("description"), + resultSet.getString("thumbnail") + ), before, after, limit); + } } diff --git a/src/main/java/roomescape/repository/ThemeRepository.java b/src/main/java/roomescape/repository/ThemeRepository.java index 211de95bbd..7d1eb65106 100644 --- a/src/main/java/roomescape/repository/ThemeRepository.java +++ b/src/main/java/roomescape/repository/ThemeRepository.java @@ -2,6 +2,7 @@ import roomescape.model.Theme; +import java.time.LocalDate; import java.util.List; public interface ThemeRepository { @@ -13,4 +14,6 @@ public interface ThemeRepository { void deleteTheme(long id); Theme findThemeById(long id); + + List findThemeRankingByDate(LocalDate before, LocalDate after, int limit); } diff --git a/src/main/java/roomescape/service/ThemeService.java b/src/main/java/roomescape/service/ThemeService.java index 5515dd8493..4fcf0b58f2 100644 --- a/src/main/java/roomescape/service/ThemeService.java +++ b/src/main/java/roomescape/service/ThemeService.java @@ -1,10 +1,12 @@ package roomescape.service; +import org.springframework.cglib.core.Local; import org.springframework.stereotype.Service; import roomescape.controller.request.ThemeRequest; import roomescape.model.Theme; import roomescape.repository.ThemeRepository; +import java.time.LocalDate; import java.util.List; @Service @@ -28,4 +30,10 @@ public Theme addTheme(ThemeRequest themeRequest) { public void deleteTheme(long id) { themeRepository.deleteTheme(id); } + + public List findPopularThemes() { + LocalDate before = LocalDate.now().minusDays(8); + LocalDate after = LocalDate.now().minusDays(1); + return themeRepository.findThemeRankingByDate(before, after, 10); + } } diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql index 875e0aa2f4..3ea97e872c 100644 --- a/src/main/resources/schema.sql +++ b/src/main/resources/schema.sql @@ -29,5 +29,5 @@ CREATE TABLE reservation INSERT INTO reservation_time (start_at) VALUES ('10:00'); INSERT INTO reservation_time (start_at) VALUES ('11:00'); -INSERT INTO theme (name, description, thumbnail) VALUES ('에버', '공포', '공포.jpg'); -INSERT INTO theme (name, description, thumbnail) VALUES ('배키', '스릴러', '스릴러.jpg'); \ No newline at end of file +INSERT INTO theme (name, description, thumbnail) VALUES ('에버', '공포', 'https://i.pinimg.com/236x/6e/bc/46/6ebc461a94a49f9ea3b8bbe2204145d4.jpg'); +INSERT INTO theme (name, description, thumbnail) VALUES ('배키', '스릴러', 'https://i.pinimg.com/236x/6e/bc/46/6ebc461a94a49f9ea3b8bbe2204145d4.jpg'); diff --git a/src/main/resources/static/js/ranking.js b/src/main/resources/static/js/ranking.js index dee05edf0b..4b0a388bbc 100644 --- a/src/main/resources/static/js/ranking.js +++ b/src/main/resources/static/js/ranking.js @@ -2,7 +2,7 @@ document.addEventListener('DOMContentLoaded', () => { /* TODO: [3단계] 인기 테마 - 인기 테마 목록 조회 API 호출 */ - requestRead('/') // 인기 테마 목록 조회 API endpoint + requestRead('/themes/rank') // 인기 테마 목록 조회 API endpoint .then(render) .catch(error => console.error('Error fetching times:', error)); }); @@ -11,13 +11,13 @@ function render(data) { const container = document.getElementById('theme-ranking'); /* - TODO: [3단계] 인기 테마 - 인기 테마 목록 조회 API 호출 후 렌더링 + TODO: 완료 [3단계] 인기 테마 - 인기 테마 목록 조회 API 호출 후 렌더링 response 명세에 맞춰 name, thumbnail, description 값 설정 */ data.forEach(theme => { - const name = ''; - const thumbnail = ''; - const description = ''; + const name = theme.name; + const thumbnail = theme.thumbnail; + const description = theme.description; const htmlContent = ` ${name} diff --git a/src/main/resources/static/js/user-reservation.js b/src/main/resources/static/js/user-reservation.js index b5454103e9..b2c5afe5c6 100644 --- a/src/main/resources/static/js/user-reservation.js +++ b/src/main/resources/static/js/user-reservation.js @@ -88,7 +88,7 @@ function checkDateAndTheme() { function fetchAvailableTimes(date, themeId) { /* - TODO: [3단계] 사용자 예약 - 예약 가능 시간 조회 API 호출 + TODO: 완료 [3단계] 사용자 예약 - 예약 가능 시간 조회 API 호출 요청 포맷에 맞게 설정 */ fetch('/reservations/times?date=' + date + '&themeId=' + themeId, { // 예약 가능 시간 조회 API endpoint @@ -117,7 +117,7 @@ function renderAvailableTimes(times) { } times.forEach(time => { /* - TODO: [3단계] 사용자 예약 - 예약 가능 시간 조회 API 호출 후 렌더링 + TODO: 완료 [3단계] 사용자 예약 - 예약 가능 시간 조회 API 호출 후 렌더링 response 명세에 맞춰 createSlot 함수 호출 시 값 설정 */ const startAt = time.startAt; diff --git a/src/test/java/roomescape/controller/ThemeControllerTest.java b/src/test/java/roomescape/controller/ThemeControllerTest.java index ca28841484..83c193323c 100644 --- a/src/test/java/roomescape/controller/ThemeControllerTest.java +++ b/src/test/java/roomescape/controller/ThemeControllerTest.java @@ -2,17 +2,23 @@ import io.restassured.RestAssured; import io.restassured.http.ContentType; -import org.assertj.core.api.AssertionsForClassTypes; +import org.junit.jupiter.api.BeforeEach; 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.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.simple.SimpleJdbcInsert; import org.springframework.test.annotation.DirtiesContext; import roomescape.controller.request.ThemeRequest; import roomescape.model.Theme; +import javax.sql.DataSource; +import java.time.LocalDate; +import java.time.LocalTime; +import java.util.HashMap; import java.util.List; +import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; @@ -23,6 +29,26 @@ class ThemeControllerTest { @Autowired JdbcTemplate jdbcTemplate; + @Autowired + DataSource dataSource; + + SimpleJdbcInsert reservationInsertActor; + SimpleJdbcInsert timeInsertActor; + SimpleJdbcInsert themeInsertActor; + + @BeforeEach + void setUp() { + reservationInsertActor = new SimpleJdbcInsert(dataSource) + .withTableName("reservation") + .usingGeneratedKeyColumns("id"); + timeInsertActor = new SimpleJdbcInsert(dataSource) + .withTableName("reservation_time") + .usingGeneratedKeyColumns("id"); + themeInsertActor = new SimpleJdbcInsert(dataSource) + .withTableName("theme") + .usingGeneratedKeyColumns("id"); + } + @DisplayName("전체 테마를 조회한다.") @Test void should_get_themes() { @@ -51,11 +77,11 @@ void should_add_theme() { .when().post("/themes") .then().log().all() .statusCode(201) - .header("Location", "/themes/1"); + .header("Location", "/themes/3"); Integer count = jdbcTemplate.queryForObject("SELECT count(1) from theme", Integer.class); - assertThat(count).isEqualTo(1); + assertThat(count).isEqualTo(3); } @DisplayName("테마를 삭제한다") @@ -70,6 +96,73 @@ void should_remove_theme() { .statusCode(204); Integer count = jdbcTemplate.queryForObject("SELECT count(1) from theme", Integer.class); - assertThat(count).isEqualTo(1); + assertThat(count).isEqualTo(3); + } + + @DisplayName("인기 테마를 조회한다.") + @Test + void should_find_popular_theme() { + jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY FALSE"); + jdbcTemplate.execute("TRUNCATE TABLE theme RESTART IDENTITY"); + jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY TRUE"); + insertReservationTime(LocalTime.of(10, 0)); + for (int i = 1; i <= 15; i++) { + insertTheme("name" + i, "description" + i, "thumbnail" + i); + } + for (int i = 1; i <= 10; i++) { + insertReservation("name" + i, LocalDate.now().minusDays(i % 7 + 1), 1L, i); + } + insertReservation("name11", LocalDate.now().minusDays(1), 1L, 10); + insertReservation("name12", LocalDate.now().minusDays(1), 1L, 10); + insertReservation("name13", LocalDate.now().minusDays(1), 1L, 10); + insertReservation("name14", LocalDate.now().minusDays(1), 1L, 9); + insertReservation("name15", LocalDate.now().minusDays(1), 1L, 9); + + Long l = jdbcTemplate.queryForObject("select count(1) from reservation", Long.class); + System.out.println(l); + + List popularThemes = RestAssured.given().log().all() + .when().get("/themes/rank") + .then().log().all() + .statusCode(200) + .extract() + .jsonPath().getList(".", Theme.class); + + assertThat(popularThemes).hasSize(10); + assertThat(popularThemes).containsExactly( + new Theme(10, "name10", "description10", "thumbnail10"), + new Theme(9, "name9", "description9", "thumbnail9"), + new Theme(1, "name1", "description1", "thumbnail1"), + new Theme(2, "name2", "description2", "thumbnail2"), + new Theme(3, "name3", "description3", "thumbnail3"), + new Theme(4, "name4", "description4", "thumbnail4"), + new Theme(5, "name5", "description5", "thumbnail5"), + new Theme(6, "name6", "description6", "thumbnail6"), + new Theme(7, "name7", "description7", "thumbnail7"), + new Theme(8, "name8", "description8", "thumbnail8") + ); + } + + private void insertReservationTime(LocalTime startAt) { + Map parameters = new HashMap<>(1); + parameters.put("start_at", startAt); + timeInsertActor.execute(parameters); + } + + private void insertReservation(String name, LocalDate date, long timeId, long themeId) { + Map parameters = new HashMap<>(4); + parameters.put("name", name); + parameters.put("date", date); + parameters.put("time_id", timeId); + parameters.put("theme_id", themeId); + reservationInsertActor.execute(parameters); + } + + private void insertTheme(String name, String description, String thumbnail) { + Map parameters = new HashMap<>(3); + parameters.put("name", name); + parameters.put("description", description); + parameters.put("thumbnail", thumbnail); + themeInsertActor.execute(parameters); } } diff --git a/src/test/java/roomescape/repository/ThemeDAOTest.java b/src/test/java/roomescape/repository/ThemeDAOTest.java index 9c3bc5d3cb..1c92978d5d 100644 --- a/src/test/java/roomescape/repository/ThemeDAOTest.java +++ b/src/test/java/roomescape/repository/ThemeDAOTest.java @@ -1,6 +1,5 @@ package roomescape.repository; -import org.assertj.core.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -12,12 +11,13 @@ import roomescape.model.Theme; import javax.sql.DataSource; - +import java.time.LocalDate; +import java.time.LocalTime; import java.util.HashMap; import java.util.List; import java.util.Map; -import static org.assertj.core.api.Assertions.*; +import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) @@ -33,6 +33,8 @@ class ThemeDAOTest { DataSource dataSource; SimpleJdbcInsert themeInsertActor; + SimpleJdbcInsert reservationInsertActor; + SimpleJdbcInsert timeInsertActor; @BeforeEach void setUp() { @@ -42,6 +44,12 @@ void setUp() { themeInsertActor = new SimpleJdbcInsert(dataSource) .withTableName("theme") .usingGeneratedKeyColumns("id"); + reservationInsertActor = new SimpleJdbcInsert(dataSource) + .withTableName("reservation") + .usingGeneratedKeyColumns("id"); + timeInsertActor = new SimpleJdbcInsert(dataSource) + .withTableName("reservation_time") + .usingGeneratedKeyColumns("id"); insertTheme("에버", "공포", "공포.jpg"); insertTheme("배키", "미스터리", "미스터리.jpg"); } @@ -75,4 +83,56 @@ void should_delete_theme() { themeRepository.deleteTheme(1); assertThat(themeRepository.findAllThemes()).hasSize(1); } + + @DisplayName("특정 기간의 테마를 인기순으로 정렬하여 조회한다.") + @Test + void should_find_ranking_theme_by_date() { + jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY FALSE"); + jdbcTemplate.execute("TRUNCATE TABLE theme RESTART IDENTITY"); + jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY TRUE"); + insertReservationTime(LocalTime.of(10, 0)); + for (int i = 1; i <= 15; i++) { + insertTheme("name" + i, "description" + i, "thumbnail" + i); + } + for (int i = 1; i <= 10; i++) { + insertReservation("name" + i, LocalDate.of(2030, 1, i % 7 + 1), 1L, i); + } + insertReservation("name11", LocalDate.of(2030, 1, 1), 1L, 10); + insertReservation("name12", LocalDate.of(2030, 1, 2), 1L, 10); + insertReservation("name13", LocalDate.of(2030, 1, 3), 1L, 10); + insertReservation("name14", LocalDate.of(2030, 1, 4), 1L, 9); + insertReservation("name15", LocalDate.of(2030, 1, 5), 1L, 9); + + LocalDate before = LocalDate.of(2030, 1, 1); + LocalDate after = LocalDate.of(2030, 1, 7); + List themes = themeRepository.findThemeRankingByDate(before, after, 10); + assertThat(themes).hasSize(10); + assertThat(themes).containsExactly( + new Theme(10, "name10", "description10", "thumbnail10"), + new Theme(9, "name9", "description9", "thumbnail9"), + new Theme(1, "name1", "description1", "thumbnail1"), + new Theme(2, "name2", "description2", "thumbnail2"), + new Theme(3, "name3", "description3", "thumbnail3"), + new Theme(4, "name4", "description4", "thumbnail4"), + new Theme(5, "name5", "description5", "thumbnail5"), + new Theme(6, "name6", "description6", "thumbnail6"), + new Theme(7, "name7", "description7", "thumbnail7"), + new Theme(8, "name8", "description8", "thumbnail8") + ); + } + + private void insertReservationTime(LocalTime startAt) { + Map parameters = new HashMap<>(1); + parameters.put("start_at", startAt); + timeInsertActor.execute(parameters); + } + + private void insertReservation(String name, LocalDate date, long timeId, long themeId) { + Map parameters = new HashMap<>(4); + parameters.put("name", name); + parameters.put("date", date); + parameters.put("time_id", timeId); + parameters.put("theme_id", themeId); + reservationInsertActor.execute(parameters); + } } \ No newline at end of file diff --git a/src/test/java/roomescape/service/FakeThemeRepository.java b/src/test/java/roomescape/service/FakeThemeRepository.java index 7ddc00de23..0be6cd07d1 100644 --- a/src/test/java/roomescape/service/FakeThemeRepository.java +++ b/src/test/java/roomescape/service/FakeThemeRepository.java @@ -3,11 +3,14 @@ import roomescape.model.Theme; import roomescape.repository.ThemeRepository; +import java.time.LocalDate; import java.util.ArrayList; import java.util.List; import java.util.NoSuchElementException; import java.util.concurrent.atomic.AtomicLong; +import static org.apache.groovy.util.Maps.of; + public class FakeThemeRepository implements ThemeRepository { private List themes = new ArrayList<>(List.of( @@ -46,4 +49,20 @@ public Theme findThemeById(long id) { .findFirst() .orElseThrow(() -> new NoSuchElementException("존재하지 않는 테마입니다.")); } + + @Override + public List findThemeRankingByDate(LocalDate before, LocalDate after, int limit) { + return List.of( + new Theme(10, "name10", "description10", "thumbnail10"), + new Theme(9, "name9", "description9", "thumbnail9"), + new Theme(1, "name1", "description1", "thumbnail1"), + new Theme(2, "name2", "description2", "thumbnail2"), + new Theme(3, "name3", "description3", "thumbnail3"), + new Theme(4, "name4", "description4", "thumbnail4"), + new Theme(5, "name5", "description5", "thumbnail5"), + new Theme(6, "name6", "description6", "thumbnail6"), + new Theme(7, "name7", "description7", "thumbnail7"), + new Theme(8, "name8", "description8", "thumbnail8") + ); + } } diff --git a/src/test/java/roomescape/service/ThemeServiceTest.java b/src/test/java/roomescape/service/ThemeServiceTest.java index cad80f69bd..85f8b3d262 100644 --- a/src/test/java/roomescape/service/ThemeServiceTest.java +++ b/src/test/java/roomescape/service/ThemeServiceTest.java @@ -3,6 +3,10 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import roomescape.controller.request.ThemeRequest; +import roomescape.model.Theme; + +import java.time.LocalDate; +import java.util.List; import static org.assertj.core.api.Assertions.*; @@ -30,4 +34,22 @@ void should_delete_theme() { themeService.deleteTheme(1L); assertThat(themeService.findAllThemes()).hasSize(2); } + + @DisplayName("최근 일주일 간 가장 인기 있는 테마 10개를 조회한다.") + @Test + void should_find_popular_theme_of_week() { + List popularThemes = themeService.findPopularThemes(); + assertThat(popularThemes).containsExactly( + new Theme(10, "name10", "description10", "thumbnail10"), + new Theme(9, "name9", "description9", "thumbnail9"), + new Theme(1, "name1", "description1", "thumbnail1"), + new Theme(2, "name2", "description2", "thumbnail2"), + new Theme(3, "name3", "description3", "thumbnail3"), + new Theme(4, "name4", "description4", "thumbnail4"), + new Theme(5, "name5", "description5", "thumbnail5"), + new Theme(6, "name6", "description6", "thumbnail6"), + new Theme(7, "name7", "description7", "thumbnail7"), + new Theme(8, "name8", "description8", "thumbnail8") + ); + } } \ No newline at end of file From e8785e79e806d3f5fce474402104c3e538f76c4f Mon Sep 17 00:00:00 2001 From: SCY Date: Thu, 2 May 2024 13:18:02 +0900 Subject: [PATCH 28/74] =?UTF-8?q?feat(GlobalExceptionHandler):=20=EC=98=88?= =?UTF-8?q?=EC=99=B8=20=ED=95=B8=EB=93=A4=EB=9F=AC=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: ehbeak --- .../exception/GlobalExceptionHandler.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/main/java/roomescape/exception/GlobalExceptionHandler.java diff --git a/src/main/java/roomescape/exception/GlobalExceptionHandler.java b/src/main/java/roomescape/exception/GlobalExceptionHandler.java new file mode 100644 index 0000000000..26e02fe599 --- /dev/null +++ b/src/main/java/roomescape/exception/GlobalExceptionHandler.java @@ -0,0 +1,25 @@ +package roomescape.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; + +@ControllerAdvice +public class GlobalExceptionHandler { + + @ExceptionHandler(value = NotFoundException.class) + public ResponseEntity handleNotFoundException(NotFoundException exception) { + return new ResponseEntity<>(exception.getMessage(), HttpStatus.NOT_FOUND); + } + + @ExceptionHandler(value = BadRequestException.class) + public ResponseEntity handleBadRequestException(BadRequestException exception) { + return new ResponseEntity<>(exception.getMessage(), HttpStatus.BAD_REQUEST); + } + + @ExceptionHandler(value = DuplicatedException.class) + public ResponseEntity handleDuplicatedException(DuplicatedException exception) { + return new ResponseEntity<>(exception.getMessage(), HttpStatus.BAD_REQUEST); + } +} From f81521de79542eb25ba18f8563691b99a1e1a74f Mon Sep 17 00:00:00 2001 From: SCY Date: Thu, 2 May 2024 13:45:09 +0900 Subject: [PATCH 29/74] =?UTF-8?q?refactor(ReservationService):=20=EC=98=88?= =?UTF-8?q?=EC=95=BD=20=EA=B0=80=EB=8A=A5=ED=95=9C=20=EC=8B=9C=EA=B0=84=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: ehbeak --- .../service/ReservationService.java | 39 +++++++++++-------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/src/main/java/roomescape/service/ReservationService.java b/src/main/java/roomescape/service/ReservationService.java index 341ba7d7e5..2ff08e38cb 100644 --- a/src/main/java/roomescape/service/ReservationService.java +++ b/src/main/java/roomescape/service/ReservationService.java @@ -1,8 +1,5 @@ package roomescape.service; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.util.List; import org.springframework.stereotype.Service; import roomescape.controller.request.ReservationRequest; import roomescape.controller.response.MemberReservationTimeResponse; @@ -16,6 +13,11 @@ import roomescape.repository.ReservationTimeRepository; import roomescape.repository.ThemeRepository; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; +import java.util.stream.Stream; + @Service public class ReservationService { @@ -61,22 +63,27 @@ public void deleteReservation(long id) { public List getMemberReservationTimes(LocalDate date, long themeId) { List allTimes = reservationTimeRepository.findAllReservationTimes(); + List bookedTimes = reservationRepository.findReservationTimeByDateAndTheme(date, themeId); + List notBookedTimes = filterNotBookedTimes(allTimes, bookedTimes); + List notBookedResponse = mapToResponse(bookedTimes, true); + List bookedResponse = mapToResponse(notBookedTimes, false); + return concat(notBookedResponse, bookedResponse); + } - List alreadyBookedTimes = reservationRepository.findReservationTimeByDateAndTheme(date, themeId); - - List responses = allTimes.stream() - .map(time -> new MemberReservationTimeResponse(time.getId(), time.getStartAt(), false)) + private List filterNotBookedTimes(List allTimes, List bookedTimes) { + return allTimes.stream() + .filter(time -> !bookedTimes.contains(time)) .toList(); + } - for (MemberReservationTimeResponse response : responses) { - for (ReservationTime alreadyBookedTime : alreadyBookedTimes) { - if (response.getTimeId() == alreadyBookedTime.getId()) { - response.setAlreadyBooked(true); - } - } - } - // TODO: 리팩토링 + private List mapToResponse(List times, boolean isBooked) { + return times.stream() + .map(time -> new MemberReservationTimeResponse(time.getId(), time.getStartAt(), isBooked)) + .toList(); + } - return responses; + private List concat(List notBookedTimes, + List bookedTimes) { + return Stream.concat(notBookedTimes.stream(), bookedTimes.stream()).toList(); } } From 2ac28fdaf26635e4322f73453784669929781435 Mon Sep 17 00:00:00 2001 From: SCY Date: Thu, 2 May 2024 13:45:38 +0900 Subject: [PATCH 30/74] =?UTF-8?q?style(all):=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=BB=A8=EB=B2=A4=EC=85=98=EC=97=90=20=EB=A7=9E=EC=B6=B0=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: ehbeak --- .../java/roomescape/RoomescapeApplication.java | 1 + .../controller/ReservationController.java | 8 ++++---- .../controller/ReservationTimeController.java | 12 ++++-------- .../roomescape/repository/ReservationDAO.java | 11 ++++++----- .../repository/ReservationRepository.java | 5 +++-- .../repository/ReservationTimeDAO.java | 11 ++++++----- .../repository/ReservationTimeRepository.java | 3 ++- .../service/ReservationTimeService.java | 5 +++-- .../java/roomescape/service/ThemeService.java | 1 - .../roomescape/RoomescapeApplicationTest.java | 6 +++--- .../controller/ReservationControllerTest.java | 10 +++++----- .../ReservationTimeControllerTest.java | 8 ++++---- .../request/ReservationRequestTest.java | 2 -- .../java/roomescape/dao/DBConnectionTest.java | 9 +++++---- .../repository/ReservationDAOTest.java | 17 +++++++++-------- .../repository/ReservationTimeDAOTest.java | 16 ++++++++-------- .../roomescape/repository/ThemeDAOTest.java | 2 +- .../service/FakeReservationTimeRepository.java | 5 +++-- .../roomescape/service/FakeThemeRepository.java | 2 -- .../service/ReservationServiceTest.java | 1 - .../service/ReservationTimeServiceTest.java | 7 +++---- .../roomescape/service/ThemeServiceTest.java | 3 +-- 22 files changed, 71 insertions(+), 74 deletions(-) diff --git a/src/main/java/roomescape/RoomescapeApplication.java b/src/main/java/roomescape/RoomescapeApplication.java index 55dcd5aa0d..ba6fc0a6a4 100644 --- a/src/main/java/roomescape/RoomescapeApplication.java +++ b/src/main/java/roomescape/RoomescapeApplication.java @@ -2,6 +2,7 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; + @SpringBootApplication public class RoomescapeApplication { diff --git a/src/main/java/roomescape/controller/ReservationController.java b/src/main/java/roomescape/controller/ReservationController.java index f2678cf608..08cec4623f 100644 --- a/src/main/java/roomescape/controller/ReservationController.java +++ b/src/main/java/roomescape/controller/ReservationController.java @@ -1,16 +1,16 @@ package roomescape.controller; -import java.net.URI; -import java.time.LocalDate; -import java.util.List; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import roomescape.controller.request.ReservationRequest; import roomescape.controller.response.MemberReservationTimeResponse; import roomescape.model.Reservation; -import roomescape.model.ReservationTime; import roomescape.service.ReservationService; +import java.net.URI; +import java.time.LocalDate; +import java.util.List; + @RestController public class ReservationController { diff --git a/src/main/java/roomescape/controller/ReservationTimeController.java b/src/main/java/roomescape/controller/ReservationTimeController.java index bdd4f546b2..18c5b35be9 100644 --- a/src/main/java/roomescape/controller/ReservationTimeController.java +++ b/src/main/java/roomescape/controller/ReservationTimeController.java @@ -1,18 +1,14 @@ package roomescape.controller; -import java.net.URI; -import java.util.List; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import roomescape.controller.request.ReservationTimeRequest; import roomescape.model.ReservationTime; import roomescape.service.ReservationTimeService; +import java.net.URI; +import java.util.List; + @RestController public class ReservationTimeController { diff --git a/src/main/java/roomescape/repository/ReservationDAO.java b/src/main/java/roomescape/repository/ReservationDAO.java index b87c888260..b0d80782b9 100644 --- a/src/main/java/roomescape/repository/ReservationDAO.java +++ b/src/main/java/roomescape/repository/ReservationDAO.java @@ -1,10 +1,5 @@ package roomescape.repository; -import java.time.LocalDate; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import javax.sql.DataSource; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.simple.SimpleJdbcInsert; import org.springframework.stereotype.Repository; @@ -12,6 +7,12 @@ import roomescape.model.ReservationTime; import roomescape.model.Theme; +import javax.sql.DataSource; +import java.time.LocalDate; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + @Repository public class ReservationDAO implements ReservationRepository { diff --git a/src/main/java/roomescape/repository/ReservationRepository.java b/src/main/java/roomescape/repository/ReservationRepository.java index 7db25e4c25..47d29ac4e9 100644 --- a/src/main/java/roomescape/repository/ReservationRepository.java +++ b/src/main/java/roomescape/repository/ReservationRepository.java @@ -1,10 +1,11 @@ package roomescape.repository; -import java.time.LocalDate; -import java.util.List; import roomescape.model.Reservation; import roomescape.model.ReservationTime; +import java.time.LocalDate; +import java.util.List; + public interface ReservationRepository { List getAllReservations(); diff --git a/src/main/java/roomescape/repository/ReservationTimeDAO.java b/src/main/java/roomescape/repository/ReservationTimeDAO.java index 2115afa3f4..204f64c8e9 100644 --- a/src/main/java/roomescape/repository/ReservationTimeDAO.java +++ b/src/main/java/roomescape/repository/ReservationTimeDAO.java @@ -1,15 +1,16 @@ package roomescape.repository; -import java.time.LocalTime; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import javax.sql.DataSource; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.simple.SimpleJdbcInsert; import org.springframework.stereotype.Repository; import roomescape.model.ReservationTime; +import javax.sql.DataSource; +import java.time.LocalTime; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + @Repository public class ReservationTimeDAO implements ReservationTimeRepository { diff --git a/src/main/java/roomescape/repository/ReservationTimeRepository.java b/src/main/java/roomescape/repository/ReservationTimeRepository.java index 2d1c41a439..5548fd5665 100644 --- a/src/main/java/roomescape/repository/ReservationTimeRepository.java +++ b/src/main/java/roomescape/repository/ReservationTimeRepository.java @@ -1,8 +1,9 @@ package roomescape.repository; +import roomescape.model.ReservationTime; + import java.time.LocalTime; import java.util.List; -import roomescape.model.ReservationTime; public interface ReservationTimeRepository { List findAllReservationTimes(); diff --git a/src/main/java/roomescape/service/ReservationTimeService.java b/src/main/java/roomescape/service/ReservationTimeService.java index a531f563c6..116bccdecf 100644 --- a/src/main/java/roomescape/service/ReservationTimeService.java +++ b/src/main/java/roomescape/service/ReservationTimeService.java @@ -1,7 +1,5 @@ package roomescape.service; -import java.time.LocalTime; -import java.util.List; import org.springframework.stereotype.Service; import roomescape.controller.request.ReservationTimeRequest; import roomescape.exception.BadRequestException; @@ -11,6 +9,9 @@ import roomescape.repository.ReservationRepository; import roomescape.repository.ReservationTimeRepository; +import java.time.LocalTime; +import java.util.List; + @Service public class ReservationTimeService { diff --git a/src/main/java/roomescape/service/ThemeService.java b/src/main/java/roomescape/service/ThemeService.java index 4fcf0b58f2..8ca077060f 100644 --- a/src/main/java/roomescape/service/ThemeService.java +++ b/src/main/java/roomescape/service/ThemeService.java @@ -1,6 +1,5 @@ package roomescape.service; -import org.springframework.cglib.core.Local; import org.springframework.stereotype.Service; import roomescape.controller.request.ThemeRequest; import roomescape.model.Theme; diff --git a/src/test/java/roomescape/RoomescapeApplicationTest.java b/src/test/java/roomescape/RoomescapeApplicationTest.java index 59dbee2a1f..a3d83ac2ad 100644 --- a/src/test/java/roomescape/RoomescapeApplicationTest.java +++ b/src/test/java/roomescape/RoomescapeApplicationTest.java @@ -6,8 +6,8 @@ @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) class RoomescapeApplicationTest { - @Test - void contextLoads() { - } + @Test + void contextLoads() { + } } diff --git a/src/test/java/roomescape/controller/ReservationControllerTest.java b/src/test/java/roomescape/controller/ReservationControllerTest.java index 705e546744..6278944137 100644 --- a/src/test/java/roomescape/controller/ReservationControllerTest.java +++ b/src/test/java/roomescape/controller/ReservationControllerTest.java @@ -1,12 +1,7 @@ package roomescape.controller; -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; - import io.restassured.RestAssured; import io.restassured.http.ContentType; -import java.lang.reflect.Field; -import java.time.LocalDate; -import java.util.List; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -17,6 +12,11 @@ import roomescape.controller.request.ReservationRequest; import roomescape.model.Reservation; +import java.lang.reflect.Field; +import java.util.List; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) diff --git a/src/test/java/roomescape/controller/ReservationTimeControllerTest.java b/src/test/java/roomescape/controller/ReservationTimeControllerTest.java index 733598d9f3..f604aae35e 100644 --- a/src/test/java/roomescape/controller/ReservationTimeControllerTest.java +++ b/src/test/java/roomescape/controller/ReservationTimeControllerTest.java @@ -1,11 +1,7 @@ package roomescape.controller; -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; - import io.restassured.RestAssured; import io.restassured.http.ContentType; -import java.time.LocalTime; -import java.util.List; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -16,6 +12,10 @@ import roomescape.controller.request.ReservationTimeRequest; import roomescape.model.ReservationTime; +import java.util.List; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) class ReservationTimeControllerTest { diff --git a/src/test/java/roomescape/controller/request/ReservationRequestTest.java b/src/test/java/roomescape/controller/request/ReservationRequestTest.java index 58022f19ce..a95711ea3a 100644 --- a/src/test/java/roomescape/controller/request/ReservationRequestTest.java +++ b/src/test/java/roomescape/controller/request/ReservationRequestTest.java @@ -7,8 +7,6 @@ import org.junit.jupiter.params.provider.ValueSource; import roomescape.exception.BadRequestException; -import java.time.LocalDate; - import static org.assertj.core.api.Assertions.assertThatThrownBy; class ReservationRequestTest { diff --git a/src/test/java/roomescape/dao/DBConnectionTest.java b/src/test/java/roomescape/dao/DBConnectionTest.java index c802944c63..e63620e849 100644 --- a/src/test/java/roomescape/dao/DBConnectionTest.java +++ b/src/test/java/roomescape/dao/DBConnectionTest.java @@ -1,9 +1,5 @@ package roomescape.dao; -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; - -import java.sql.Connection; -import java.sql.SQLException; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -11,6 +7,11 @@ import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.test.annotation.DirtiesContext; +import java.sql.Connection; +import java.sql.SQLException; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) class DBConnectionTest { diff --git a/src/test/java/roomescape/repository/ReservationDAOTest.java b/src/test/java/roomescape/repository/ReservationDAOTest.java index 08f156d770..25b994a819 100644 --- a/src/test/java/roomescape/repository/ReservationDAOTest.java +++ b/src/test/java/roomescape/repository/ReservationDAOTest.java @@ -1,13 +1,5 @@ package roomescape.repository; -import static org.assertj.core.api.Assertions.assertThat; - -import java.time.LocalDate; -import java.time.LocalTime; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import javax.sql.DataSource; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -20,6 +12,15 @@ import roomescape.model.ReservationTime; import roomescape.model.Theme; +import javax.sql.DataSource; +import java.time.LocalDate; +import java.time.LocalTime; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) class ReservationDAOTest { diff --git a/src/test/java/roomescape/repository/ReservationTimeDAOTest.java b/src/test/java/roomescape/repository/ReservationTimeDAOTest.java index 5e25e70ad5..4177cfeb89 100644 --- a/src/test/java/roomescape/repository/ReservationTimeDAOTest.java +++ b/src/test/java/roomescape/repository/ReservationTimeDAOTest.java @@ -1,13 +1,5 @@ package roomescape.repository; -import static org.assertj.core.api.Assertions.assertThat; - -import java.time.LocalTime; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import javax.sql.DataSource; - import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -18,6 +10,14 @@ import org.springframework.test.annotation.DirtiesContext; import roomescape.model.ReservationTime; +import javax.sql.DataSource; +import java.time.LocalTime; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) class ReservationTimeDAOTest { diff --git a/src/test/java/roomescape/repository/ThemeDAOTest.java b/src/test/java/roomescape/repository/ThemeDAOTest.java index 1c92978d5d..91d644da42 100644 --- a/src/test/java/roomescape/repository/ThemeDAOTest.java +++ b/src/test/java/roomescape/repository/ThemeDAOTest.java @@ -118,7 +118,7 @@ void should_find_ranking_theme_by_date() { new Theme(6, "name6", "description6", "thumbnail6"), new Theme(7, "name7", "description7", "thumbnail7"), new Theme(8, "name8", "description8", "thumbnail8") - ); + ); } private void insertReservationTime(LocalTime startAt) { diff --git a/src/test/java/roomescape/service/FakeReservationTimeRepository.java b/src/test/java/roomescape/service/FakeReservationTimeRepository.java index 51229c1a36..a56393f715 100644 --- a/src/test/java/roomescape/service/FakeReservationTimeRepository.java +++ b/src/test/java/roomescape/service/FakeReservationTimeRepository.java @@ -1,11 +1,12 @@ package roomescape.service; +import roomescape.model.ReservationTime; +import roomescape.repository.ReservationTimeRepository; + import java.time.LocalTime; import java.util.ArrayList; import java.util.List; import java.util.NoSuchElementException; -import roomescape.model.ReservationTime; -import roomescape.repository.ReservationTimeRepository; class FakeReservationTimeRepository implements ReservationTimeRepository { diff --git a/src/test/java/roomescape/service/FakeThemeRepository.java b/src/test/java/roomescape/service/FakeThemeRepository.java index 0be6cd07d1..e6efe5a3c9 100644 --- a/src/test/java/roomescape/service/FakeThemeRepository.java +++ b/src/test/java/roomescape/service/FakeThemeRepository.java @@ -9,8 +9,6 @@ import java.util.NoSuchElementException; import java.util.concurrent.atomic.AtomicLong; -import static org.apache.groovy.util.Maps.of; - public class FakeThemeRepository implements ThemeRepository { private List themes = new ArrayList<>(List.of( diff --git a/src/test/java/roomescape/service/ReservationServiceTest.java b/src/test/java/roomescape/service/ReservationServiceTest.java index 54e6c40b05..4cb3622073 100644 --- a/src/test/java/roomescape/service/ReservationServiceTest.java +++ b/src/test/java/roomescape/service/ReservationServiceTest.java @@ -3,7 +3,6 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import roomescape.controller.request.ReservationRequest; -import roomescape.controller.request.ReservationTimeRequest; import roomescape.exception.BadRequestException; import roomescape.exception.DuplicatedException; import roomescape.exception.NotFoundException; diff --git a/src/test/java/roomescape/service/ReservationTimeServiceTest.java b/src/test/java/roomescape/service/ReservationTimeServiceTest.java index d6b63148d0..1064c2b4b6 100644 --- a/src/test/java/roomescape/service/ReservationTimeServiceTest.java +++ b/src/test/java/roomescape/service/ReservationTimeServiceTest.java @@ -1,9 +1,5 @@ package roomescape.service; -import java.time.LocalTime; -import java.util.List; - -import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import roomescape.controller.request.ReservationTimeRequest; @@ -12,6 +8,9 @@ import roomescape.exception.NotFoundException; import roomescape.model.ReservationTime; +import java.time.LocalTime; +import java.util.List; + import static org.assertj.core.api.Assertions.*; class ReservationTimeServiceTest { diff --git a/src/test/java/roomescape/service/ThemeServiceTest.java b/src/test/java/roomescape/service/ThemeServiceTest.java index 85f8b3d262..5666210999 100644 --- a/src/test/java/roomescape/service/ThemeServiceTest.java +++ b/src/test/java/roomescape/service/ThemeServiceTest.java @@ -5,10 +5,9 @@ import roomescape.controller.request.ThemeRequest; import roomescape.model.Theme; -import java.time.LocalDate; import java.util.List; -import static org.assertj.core.api.Assertions.*; +import static org.assertj.core.api.Assertions.assertThat; class ThemeServiceTest { From 838d102a0517be7e63176fcc50ba17c1b0b59c1c Mon Sep 17 00:00:00 2001 From: SCY Date: Thu, 2 May 2024 14:52:59 +0900 Subject: [PATCH 31/74] =?UTF-8?q?test(reservation):=20=EC=98=88=EC=95=BD?= =?UTF-8?q?=20=EA=B0=80=EB=8A=A5=20=EC=8B=9C=EA=B0=84=20=EC=A1=B0=ED=9A=8C?= =?UTF-8?q?=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: ehbeak --- .../response/MemberReservationTimeResponse.java | 14 ++++++++++++++ .../java/roomescape/model/ReservationTime.java | 14 ++++++++++++++ .../roomescape/service/ReservationService.java | 4 ++-- .../roomescape/repository/ReservationDAOTest.java | 9 +++++++++ .../service/FakeReservationRepository.java | 4 ++-- .../roomescape/service/ReservationServiceTest.java | 14 ++++++++++++++ 6 files changed, 55 insertions(+), 4 deletions(-) diff --git a/src/main/java/roomescape/controller/response/MemberReservationTimeResponse.java b/src/main/java/roomescape/controller/response/MemberReservationTimeResponse.java index 7825573646..186140b5d0 100644 --- a/src/main/java/roomescape/controller/response/MemberReservationTimeResponse.java +++ b/src/main/java/roomescape/controller/response/MemberReservationTimeResponse.java @@ -1,6 +1,7 @@ package roomescape.controller.response; import java.time.LocalTime; +import java.util.Objects; public class MemberReservationTimeResponse { @@ -29,4 +30,17 @@ public LocalTime getStartAt() { public boolean getAlreadyBooked() { return alreadyBooked; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + MemberReservationTimeResponse that = (MemberReservationTimeResponse) o; + return timeId == that.timeId && alreadyBooked == that.alreadyBooked && Objects.equals(startAt, that.startAt); + } + + @Override + public int hashCode() { + return Objects.hash(timeId, startAt, alreadyBooked); + } } diff --git a/src/main/java/roomescape/model/ReservationTime.java b/src/main/java/roomescape/model/ReservationTime.java index 9a2b6eeafb..b3f62e4f67 100644 --- a/src/main/java/roomescape/model/ReservationTime.java +++ b/src/main/java/roomescape/model/ReservationTime.java @@ -1,6 +1,7 @@ package roomescape.model; import java.time.LocalTime; +import java.util.Objects; public class ReservationTime { @@ -26,4 +27,17 @@ public long getId() { public LocalTime getStartAt() { return startAt; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ReservationTime that = (ReservationTime) o; + return id == that.id && Objects.equals(startAt, that.startAt); + } + + @Override + public int hashCode() { + return Objects.hash(id, startAt); + } } diff --git a/src/main/java/roomescape/service/ReservationService.java b/src/main/java/roomescape/service/ReservationService.java index 2ff08e38cb..1130712190 100644 --- a/src/main/java/roomescape/service/ReservationService.java +++ b/src/main/java/roomescape/service/ReservationService.java @@ -65,8 +65,8 @@ public List getMemberReservationTimes(LocalDate d List allTimes = reservationTimeRepository.findAllReservationTimes(); List bookedTimes = reservationRepository.findReservationTimeByDateAndTheme(date, themeId); List notBookedTimes = filterNotBookedTimes(allTimes, bookedTimes); - List notBookedResponse = mapToResponse(bookedTimes, true); - List bookedResponse = mapToResponse(notBookedTimes, false); + List bookedResponse = mapToResponse(bookedTimes, true); + List notBookedResponse = mapToResponse(notBookedTimes, false); return concat(notBookedResponse, bookedResponse); } diff --git a/src/test/java/roomescape/repository/ReservationDAOTest.java b/src/test/java/roomescape/repository/ReservationDAOTest.java index 25b994a819..c6f6ba6fb3 100644 --- a/src/test/java/roomescape/repository/ReservationDAOTest.java +++ b/src/test/java/roomescape/repository/ReservationDAOTest.java @@ -138,4 +138,13 @@ void should_return_false_when_id_not_exist() { long count = reservationRepository.countReservationById(100000000); assertThat(count).isEqualTo(0); } + + @DisplayName("특정 날짜와 테마에 해당하는 시간을 조회한다.") + @Test + void should_get_reservation_times_when_date_and_theme_given() { + LocalDate date = LocalDate.of(2023, 8, 5); + List times = reservationRepository.findReservationTimeByDateAndTheme(date, 1); + assertThat(times).hasSize(1); + assertThat(times).containsExactly(new ReservationTime(1, LocalTime.of(10, 0))); + } } diff --git a/src/test/java/roomescape/service/FakeReservationRepository.java b/src/test/java/roomescape/service/FakeReservationRepository.java index 02ec7f96f8..ea0a31ced9 100644 --- a/src/test/java/roomescape/service/FakeReservationRepository.java +++ b/src/test/java/roomescape/service/FakeReservationRepository.java @@ -66,8 +66,8 @@ public Long countReservationByDateAndTimeId(LocalDate date, long timeId) { @Override public List findReservationTimeByDateAndTheme(LocalDate date, long themeId) { return reservations.stream() - .filter(reservation -> reservation.getDate() == date && reservation.getTheme().getThemeId() == themeId) - .map(reservation -> new ReservationTime(reservation.getId(), reservation.getTime().getStartAt())) + .filter(reservation -> reservation.getDate().equals(date) && reservation.getTheme().getThemeId() == themeId) + .map(reservation -> new ReservationTime(reservation.getTime().getId(), reservation.getTime().getStartAt())) .toList(); } } \ No newline at end of file diff --git a/src/test/java/roomescape/service/ReservationServiceTest.java b/src/test/java/roomescape/service/ReservationServiceTest.java index 4cb3622073..7fa5941d61 100644 --- a/src/test/java/roomescape/service/ReservationServiceTest.java +++ b/src/test/java/roomescape/service/ReservationServiceTest.java @@ -3,11 +3,14 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import roomescape.controller.request.ReservationRequest; +import roomescape.controller.response.MemberReservationTimeResponse; import roomescape.exception.BadRequestException; import roomescape.exception.DuplicatedException; import roomescape.exception.NotFoundException; import roomescape.model.Reservation; +import java.time.LocalDate; +import java.time.LocalTime; import java.util.List; import static org.assertj.core.api.Assertions.*; @@ -83,4 +86,15 @@ void should_throw_exception_when_add_exist_reservation() { .isInstanceOf(DuplicatedException.class) .hasMessage("[ERROR] 중복되는 예약은 추가할 수 없습니다."); } + + @DisplayName("예약 가능 상태를 담은 시간 정보를 반환한다.") + @Test + void should_return_times_with_book_state() { + List times = reservationService.getMemberReservationTimes(LocalDate.of(2030, 8, 5), 1); + assertThat(times).hasSize(2); + assertThat(times).containsOnly( + new MemberReservationTimeResponse(1, LocalTime.of(10, 0), false), + new MemberReservationTimeResponse(2, LocalTime.of(11, 0), true) + ); + } } From f555d309d7611e371285aba068ef0aeca2259a37 Mon Sep 17 00:00:00 2001 From: SCY Date: Thu, 2 May 2024 15:19:15 +0900 Subject: [PATCH 32/74] =?UTF-8?q?style(test):=20=EC=9D=B8=EC=8A=A4?= =?UTF-8?q?=ED=84=B4=EC=8A=A4=20=ED=95=84=EB=93=9C=20=EC=BB=A8=EB=B2=A4?= =?UTF-8?q?=EC=85=98=20=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: ehbeak --- .../controller/ReservationControllerTest.java | 4 +++- .../controller/ThemeControllerTest.java | 10 +++++----- .../repository/ReservationDAOTest.java | 14 ++++++------- .../repository/ReservationTimeDAOTest.java | 20 +++++++++---------- .../roomescape/repository/ThemeDAOTest.java | 12 +++++------ .../service/ReservationServiceTest.java | 3 ++- .../service/ReservationTimeServiceTest.java | 3 ++- .../roomescape/service/ThemeServiceTest.java | 2 +- 8 files changed, 35 insertions(+), 33 deletions(-) diff --git a/src/test/java/roomescape/controller/ReservationControllerTest.java b/src/test/java/roomescape/controller/ReservationControllerTest.java index 6278944137..b9ba5529dd 100644 --- a/src/test/java/roomescape/controller/ReservationControllerTest.java +++ b/src/test/java/roomescape/controller/ReservationControllerTest.java @@ -23,7 +23,7 @@ class ReservationControllerTest { @Autowired - JdbcTemplate jdbcTemplate; + private JdbcTemplate jdbcTemplate; @Autowired private ReservationController reservationController; @@ -103,4 +103,6 @@ void should_not_exist_JdbcTemplate_field() { assertThat(isJdbcTemplateInjected).isFalse(); } + + // TODO: 예약 가능 시간 조회 컨트롤러 테스트!!!! } diff --git a/src/test/java/roomescape/controller/ThemeControllerTest.java b/src/test/java/roomescape/controller/ThemeControllerTest.java index 83c193323c..c45173083d 100644 --- a/src/test/java/roomescape/controller/ThemeControllerTest.java +++ b/src/test/java/roomescape/controller/ThemeControllerTest.java @@ -27,14 +27,14 @@ class ThemeControllerTest { @Autowired - JdbcTemplate jdbcTemplate; + private DataSource dataSource; @Autowired - DataSource dataSource; + private JdbcTemplate jdbcTemplate; - SimpleJdbcInsert reservationInsertActor; - SimpleJdbcInsert timeInsertActor; - SimpleJdbcInsert themeInsertActor; + private SimpleJdbcInsert reservationInsertActor; + private SimpleJdbcInsert timeInsertActor; + private SimpleJdbcInsert themeInsertActor; @BeforeEach void setUp() { diff --git a/src/test/java/roomescape/repository/ReservationDAOTest.java b/src/test/java/roomescape/repository/ReservationDAOTest.java index c6f6ba6fb3..360b923e4d 100644 --- a/src/test/java/roomescape/repository/ReservationDAOTest.java +++ b/src/test/java/roomescape/repository/ReservationDAOTest.java @@ -26,19 +26,17 @@ class ReservationDAOTest { @Autowired - JdbcTemplate jdbcTemplate; + private JdbcTemplate jdbcTemplate; @Autowired - ReservationRepository reservationRepository; + private ReservationRepository reservationRepository; @Autowired - DataSource dataSource; + private DataSource dataSource; - SimpleJdbcInsert reservationTimeInsertActor; - - SimpleJdbcInsert reservationInsertActor; - - SimpleJdbcInsert themeInsertActor; + private SimpleJdbcInsert reservationTimeInsertActor; + private SimpleJdbcInsert reservationInsertActor; + private SimpleJdbcInsert themeInsertActor; @BeforeEach void setUp() { diff --git a/src/test/java/roomescape/repository/ReservationTimeDAOTest.java b/src/test/java/roomescape/repository/ReservationTimeDAOTest.java index 4177cfeb89..53ba07235c 100644 --- a/src/test/java/roomescape/repository/ReservationTimeDAOTest.java +++ b/src/test/java/roomescape/repository/ReservationTimeDAOTest.java @@ -23,15 +23,15 @@ class ReservationTimeDAOTest { @Autowired - JdbcTemplate jdbcTemplate; + private JdbcTemplate jdbcTemplate; @Autowired - DataSource dataSource; + private DataSource dataSource; @Autowired - ReservationTimeDAO reservationTimeDAOImpl; + private ReservationTimeRepository reservationTimeRepository; - SimpleJdbcInsert insertActor; + private SimpleJdbcInsert insertActor; @BeforeEach void setUp() { @@ -55,14 +55,14 @@ private void insertToReservationTime(String startAt) { @DisplayName("모든 예약 시간을 조회한다") @Test void should_get_reservation_times() { - List reservationTimes = reservationTimeDAOImpl.findAllReservationTimes(); + List reservationTimes = reservationTimeRepository.findAllReservationTimes(); assertThat(reservationTimes).hasSize(2); } @DisplayName("예약 시간을 추가한다") @Test void should_add_reservation_time() { - reservationTimeDAOImpl.addReservationTime(new ReservationTime(LocalTime.of(12, 0))); + reservationTimeRepository.addReservationTime(new ReservationTime(LocalTime.of(12, 0))); Integer count = jdbcTemplate.queryForObject("select count(1) from reservation_time", Integer.class); assertThat(count).isEqualTo(3); } @@ -70,7 +70,7 @@ void should_add_reservation_time() { @DisplayName("예약 시간을 삭제한다") @Test void should_delete_reservation_time() { - reservationTimeDAOImpl.deleteReservationTime(1); + reservationTimeRepository.deleteReservationTime(1); Integer count = jdbcTemplate.queryForObject("select count(1) from reservation_time", Integer.class); assertThat(count).isEqualTo(1); } @@ -78,21 +78,21 @@ void should_delete_reservation_time() { @DisplayName("아이디에 해당하는 예약 시간을 조회한다.") @Test void should_get_reservation_time() { - ReservationTime reservationTime = reservationTimeDAOImpl.findReservationById(1); + ReservationTime reservationTime = reservationTimeRepository.findReservationById(1); assertThat(reservationTime.getStartAt()).isEqualTo(LocalTime.of(10, 0)); } @DisplayName("아이디가 존재하면 참을 반환한다.") @Test void should_return_true_when_id_exist() { - long count = reservationTimeDAOImpl.countReservationTimeById(1); + long count = reservationTimeRepository.countReservationTimeById(1); assertThat(count).isEqualTo(1); } @DisplayName("아이디가 존재하면 거짓을 반환한다.") @Test void should_return_false_when_id_not_exist() { - long count = reservationTimeDAOImpl.countReservationTimeById(100000000); + long count = reservationTimeRepository.countReservationTimeById(100000000); assertThat(count).isEqualTo(0); } } diff --git a/src/test/java/roomescape/repository/ThemeDAOTest.java b/src/test/java/roomescape/repository/ThemeDAOTest.java index 91d644da42..e76c546390 100644 --- a/src/test/java/roomescape/repository/ThemeDAOTest.java +++ b/src/test/java/roomescape/repository/ThemeDAOTest.java @@ -24,17 +24,17 @@ class ThemeDAOTest { @Autowired - ThemeRepository themeRepository; + private DataSource dataSource; @Autowired - JdbcTemplate jdbcTemplate; + private JdbcTemplate jdbcTemplate; @Autowired - DataSource dataSource; + private ThemeRepository themeRepository; - SimpleJdbcInsert themeInsertActor; - SimpleJdbcInsert reservationInsertActor; - SimpleJdbcInsert timeInsertActor; + private SimpleJdbcInsert themeInsertActor; + private SimpleJdbcInsert reservationInsertActor; + private SimpleJdbcInsert timeInsertActor; @BeforeEach void setUp() { diff --git a/src/test/java/roomescape/service/ReservationServiceTest.java b/src/test/java/roomescape/service/ReservationServiceTest.java index 7fa5941d61..662abb054d 100644 --- a/src/test/java/roomescape/service/ReservationServiceTest.java +++ b/src/test/java/roomescape/service/ReservationServiceTest.java @@ -16,7 +16,8 @@ import static org.assertj.core.api.Assertions.*; class ReservationServiceTest { - ReservationService reservationService = new ReservationService( + + private final ReservationService reservationService = new ReservationService( new FakeReservationRepository(), new FakeReservationTimeRepository(), new FakeThemeRepository()); diff --git a/src/test/java/roomescape/service/ReservationTimeServiceTest.java b/src/test/java/roomescape/service/ReservationTimeServiceTest.java index 1064c2b4b6..6c509c24bb 100644 --- a/src/test/java/roomescape/service/ReservationTimeServiceTest.java +++ b/src/test/java/roomescape/service/ReservationTimeServiceTest.java @@ -14,7 +14,8 @@ import static org.assertj.core.api.Assertions.*; class ReservationTimeServiceTest { - ReservationTimeService reservationTimeService = new ReservationTimeService( + + private final ReservationTimeService reservationTimeService = new ReservationTimeService( new FakeReservationRepository(), new FakeReservationTimeRepository() ); diff --git a/src/test/java/roomescape/service/ThemeServiceTest.java b/src/test/java/roomescape/service/ThemeServiceTest.java index 5666210999..b19ea7e5af 100644 --- a/src/test/java/roomescape/service/ThemeServiceTest.java +++ b/src/test/java/roomescape/service/ThemeServiceTest.java @@ -11,7 +11,7 @@ class ThemeServiceTest { - ThemeService themeService = new ThemeService(new FakeThemeRepository()); + private final ThemeService themeService = new ThemeService(new FakeThemeRepository()); @DisplayName("테마를 조회한다.") @Test From 5113931556440ec198fb574837da8f3932aec3d6 Mon Sep 17 00:00:00 2001 From: SCY Date: Thu, 2 May 2024 15:30:14 +0900 Subject: [PATCH 33/74] =?UTF-8?q?test(ReservationControllerTest):=20?= =?UTF-8?q?=ED=8A=B9=EC=A0=95=20=EB=82=A0=EC=A7=9C=EC=99=80=20=ED=85=8C?= =?UTF-8?q?=EB=A7=88=EC=97=90=20=EB=94=B0=EB=A5=B8=20=EB=AA=A8=EB=93=A0=20?= =?UTF-8?q?=EC=8B=9C=EA=B0=84=EC=9D=98=20=EC=98=88=EC=95=BD=20=EA=B0=80?= =?UTF-8?q?=EB=8A=A5=20=EC=97=AC=EB=B6=80=20=ED=99=95=EC=9D=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: ehbeak --- .../controller/ReservationControllerTest.java | 30 +++++++++++++++---- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/src/test/java/roomescape/controller/ReservationControllerTest.java b/src/test/java/roomescape/controller/ReservationControllerTest.java index b9ba5529dd..b44691e037 100644 --- a/src/test/java/roomescape/controller/ReservationControllerTest.java +++ b/src/test/java/roomescape/controller/ReservationControllerTest.java @@ -3,6 +3,7 @@ import io.restassured.RestAssured; import io.restassured.http.ContentType; import org.assertj.core.api.Assertions; +import org.assertj.core.api.AssertionsForClassTypes; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -10,11 +11,14 @@ import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.test.annotation.DirtiesContext; import roomescape.controller.request.ReservationRequest; +import roomescape.controller.response.MemberReservationTimeResponse; import roomescape.model.Reservation; import java.lang.reflect.Field; +import java.time.LocalTime; import java.util.List; +import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; @@ -43,7 +47,7 @@ void should_get_reservations() { Integer count = jdbcTemplate.queryForObject("SELECT count(1) from reservation", Integer.class); - Assertions.assertThat(reservations).hasSize(count); + assertThat(reservations).hasSize(count); } @DisplayName("예약을 추가할 수 있다.") @@ -67,7 +71,7 @@ void should_insert_reservation() { .header("Location", "/reservations/1"); Integer count = jdbcTemplate.queryForObject("SELECT count(1) from reservation", Integer.class); - assertThat(count).isEqualTo(1); + AssertionsForClassTypes.assertThat(count).isEqualTo(1); } @DisplayName("존재하는 예약이라면 예약을 삭제할 수 있다.") @@ -86,7 +90,7 @@ void should_delete_reservation_when_reservation_exist() { .statusCode(204); Integer countAfterDelete = jdbcTemplate.queryForObject("SELECT count(1) from reservation", Integer.class); - assertThat(countAfterDelete).isZero(); + AssertionsForClassTypes.assertThat(countAfterDelete).isZero(); } @DisplayName("컨트롤러에 JdbcTemplate 필드가 존재하지 않는다.") @@ -101,8 +105,24 @@ void should_not_exist_JdbcTemplate_field() { } } - assertThat(isJdbcTemplateInjected).isFalse(); + AssertionsForClassTypes.assertThat(isJdbcTemplateInjected).isFalse(); } - // TODO: 예약 가능 시간 조회 컨트롤러 테스트!!!! + @DisplayName("특정 날짜와 테마에 따른 모든 시간의 예약 가능 여부를 확인한다.") + @Test + void should_get_reservations_with_book_state_by_date_and_theme() { + jdbcTemplate.update("INSERT INTO reservation (name, date, time_id, theme_id) VALUES (?, ?, ?, ?)", "브라운", "2030-08-05", "1", "1"); + + List responses = RestAssured.given().log().all() + .when().get("/reservations/times?date=2030-08-05&themeId=1") + .then().log().all() + .statusCode(200).extract() + .jsonPath().getList(".", MemberReservationTimeResponse.class); + + assertThat(responses).hasSize(2); + assertThat(responses).containsOnly( + new MemberReservationTimeResponse(1, LocalTime.of(10, 0), true), + new MemberReservationTimeResponse(2, LocalTime.of(11, 0), false) + ); + } } From e548036234beac4bdd2fbd513f2016aad5bb992a Mon Sep 17 00:00:00 2001 From: SCY Date: Thu, 2 May 2024 15:45:35 +0900 Subject: [PATCH 34/74] =?UTF-8?q?test(ReservationServiceTest):=20=ED=98=84?= =?UTF-8?q?=EC=9E=AC=EB=A1=9C=20=EC=98=88=EC=95=BD=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=EA=B2=BD=EC=9A=B0=20=EA=B2=BD=EA=B3=84=EA=B0=92=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: ehbeak --- .../roomescape/service/ReservationService.java | 7 ++++++- .../service/FakeReservationTimeRepository.java | 4 ++++ .../service/ReservationServiceTest.java | 17 +++++++++++++++-- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/main/java/roomescape/service/ReservationService.java b/src/main/java/roomescape/service/ReservationService.java index 1130712190..623e369864 100644 --- a/src/main/java/roomescape/service/ReservationService.java +++ b/src/main/java/roomescape/service/ReservationService.java @@ -15,6 +15,8 @@ import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.time.temporal.ChronoUnit; import java.util.List; import java.util.stream.Stream; @@ -42,7 +44,10 @@ public Reservation addReservation(ReservationRequest request) { Theme theme = themeRepository.findThemeById(request.getThemeId()); LocalDateTime reservationDateTime = LocalDateTime.of(request.getDate(), reservationTime.getStartAt()); - if (reservationDateTime.isBefore(LocalDateTime.now())) { + + LocalDateTime requestDateTime = reservationDateTime.truncatedTo(ChronoUnit.SECONDS); + LocalDateTime now = LocalDateTime.now().truncatedTo(ChronoUnit.SECONDS); + if (requestDateTime.isBefore(now)) { throw new BadRequestException("[ERROR] 현재 이전 예약은 할 수 없습니다."); } Long countReservation = reservationRepository.countReservationByDateAndTimeId(request.getDate(), request.getTimeId()); diff --git a/src/test/java/roomescape/service/FakeReservationTimeRepository.java b/src/test/java/roomescape/service/FakeReservationTimeRepository.java index a56393f715..97cb3f8bd8 100644 --- a/src/test/java/roomescape/service/FakeReservationTimeRepository.java +++ b/src/test/java/roomescape/service/FakeReservationTimeRepository.java @@ -15,6 +15,10 @@ class FakeReservationTimeRepository implements ReservationTimeRepository { new ReservationTime(2, LocalTime.of(11, 0)) )); + public void add(ReservationTime reservationTime) { + reservationTimes.add(reservationTime); + } + @Override public List findAllReservationTimes() { return reservationTimes; diff --git a/src/test/java/roomescape/service/ReservationServiceTest.java b/src/test/java/roomescape/service/ReservationServiceTest.java index 662abb054d..6900c82220 100644 --- a/src/test/java/roomescape/service/ReservationServiceTest.java +++ b/src/test/java/roomescape/service/ReservationServiceTest.java @@ -1,5 +1,6 @@ package roomescape.service; +import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import roomescape.controller.request.ReservationRequest; @@ -8,6 +9,8 @@ import roomescape.exception.DuplicatedException; import roomescape.exception.NotFoundException; import roomescape.model.Reservation; +import roomescape.model.ReservationTime; +import roomescape.repository.ReservationTimeRepository; import java.time.LocalDate; import java.time.LocalTime; @@ -17,9 +20,11 @@ class ReservationServiceTest { + private final FakeReservationTimeRepository reservationTimeRepository = new FakeReservationTimeRepository(); + private final ReservationService reservationService = new ReservationService( new FakeReservationRepository(), - new FakeReservationTimeRepository(), + reservationTimeRepository, new FakeThemeRepository()); @DisplayName("모든 예약 시간을 반환한다") @@ -61,7 +66,6 @@ void should_not_throw_exception_when_exist_reservation_time() { .doesNotThrowAnyException(); } - //todo 현재 시간에 따라 테스트 깨짐 + 경계값 테스트 @DisplayName("현재 이전으로 예약하면 예외가 발생한다.") @Test void should_throw_exception_when_previous_date() { @@ -71,6 +75,15 @@ void should_throw_exception_when_previous_date() { .hasMessage("[ERROR] 현재 이전 예약은 할 수 없습니다."); } + @DisplayName("현재로 예약하면 예외가 발생하지 않는다.") + @Test + void should_not_throw_exception_when_current_date() { + reservationTimeRepository.add(new ReservationTime(3, LocalTime.now())); + ReservationRequest request = new ReservationRequest(LocalDate.now().toString(), "에버", 3, 1); + assertThatCode(() -> reservationService.addReservation(request)) + .doesNotThrowAnyException(); + } + @DisplayName("현재 이후로 예약하면 예외가 발생하지 않는다.") @Test void should_not_throw_exception_when_later_date() { From f2c69b7fd504d73803014d50838450dd5f9109e9 Mon Sep 17 00:00:00 2001 From: SCY Date: Thu, 2 May 2024 16:52:19 +0900 Subject: [PATCH 35/74] =?UTF-8?q?refactor(request):=20=EC=9C=A0=ED=9A=A8?= =?UTF-8?q?=ED=95=98=EC=A7=80=20=EC=95=8A=EC=9D=80=20=EC=9A=94=EC=B2=AD=20?= =?UTF-8?q?=EC=8B=9C=20=EC=98=88=EC=99=B8=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: ehbeak --- .../request/ReservationRequest.java | 30 +++++++------------ .../request/ReservationTimeRequest.java | 15 ++++------ .../controller/request/ThemeRequest.java | 17 +++++++++-- .../exception/GlobalExceptionHandler.java | 7 +++++ .../controller/ReservationControllerTest.java | 7 +++-- .../ReservationTimeControllerTest.java | 3 +- .../request/ReservationRequestTest.java | 10 +++---- .../request/ReservationTimeRequestTest.java | 21 ++----------- .../service/ReservationServiceTest.java | 10 +++---- .../service/ReservationTimeServiceTest.java | 4 +-- 10 files changed, 58 insertions(+), 66 deletions(-) diff --git a/src/main/java/roomescape/controller/request/ReservationRequest.java b/src/main/java/roomescape/controller/request/ReservationRequest.java index 5209bdc6b8..adef18958a 100644 --- a/src/main/java/roomescape/controller/request/ReservationRequest.java +++ b/src/main/java/roomescape/controller/request/ReservationRequest.java @@ -3,39 +3,31 @@ import roomescape.exception.BadRequestException; import java.time.LocalDate; -import java.time.format.DateTimeParseException; public class ReservationRequest { - private LocalDate date; - private String name; - private long timeId; - private long themeId; + private final String name; + private final LocalDate date; + private final long timeId; + private final long themeId; - public ReservationRequest(String date, String name, long timeId, long themeId) { + public ReservationRequest(String name, LocalDate date, Long timeId, Long themeId) { validateName(name); - validateDate(date); - try { - this.date = LocalDate.parse(date); - } catch (DateTimeParseException exception) { - throw new BadRequestException("[ERROR] 유효하지 않은 요청입니다."); - } + validateNull(date, timeId, themeId); this.name = name; + this.date = date; this.timeId = timeId; this.themeId = themeId; } - private ReservationRequest() { - } - - private void validateDate(String date) { - if (date == null || date.isEmpty()) { + private void validateName(String name) { + if (name == null || name.isEmpty()) { throw new BadRequestException("[ERROR] 유효하지 않은 요청입니다."); } } - private void validateName(String name) { - if (name == null || name.isEmpty()) { + private void validateNull(LocalDate date, Long timeId, Long themeId) { + if (date == null || timeId == null || themeId == null) { throw new BadRequestException("[ERROR] 유효하지 않은 요청입니다."); } } diff --git a/src/main/java/roomescape/controller/request/ReservationTimeRequest.java b/src/main/java/roomescape/controller/request/ReservationTimeRequest.java index 704a001bc5..d6e5084c3b 100644 --- a/src/main/java/roomescape/controller/request/ReservationTimeRequest.java +++ b/src/main/java/roomescape/controller/request/ReservationTimeRequest.java @@ -3,26 +3,21 @@ import roomescape.exception.BadRequestException; import java.time.LocalTime; -import java.time.format.DateTimeParseException; public class ReservationTimeRequest { private LocalTime startAt; - public ReservationTimeRequest(String startAt) { - validate(startAt); - try { - this.startAt = LocalTime.parse(startAt); - } catch (DateTimeParseException exception) { - throw new BadRequestException("[ERROR] 유효하지 않은 요청입니다."); - } + public ReservationTimeRequest(LocalTime startAt) { + validateTime(startAt); + this.startAt = startAt; } private ReservationTimeRequest() { } - private void validate(String startAt) { - if (startAt == null || startAt.isEmpty()) { + private void validateTime(LocalTime startAt) { + if (startAt == null) { throw new BadRequestException("[ERROR] 유효하지 않은 요청입니다."); } } diff --git a/src/main/java/roomescape/controller/request/ThemeRequest.java b/src/main/java/roomescape/controller/request/ThemeRequest.java index f5a998629d..d04cf7fcf9 100644 --- a/src/main/java/roomescape/controller/request/ThemeRequest.java +++ b/src/main/java/roomescape/controller/request/ThemeRequest.java @@ -1,17 +1,28 @@ package roomescape.controller.request; +import roomescape.exception.BadRequestException; + public class ThemeRequest { - private String name; - private String description; - private String thumbnail; + private final String name; + private final String description; + private final String thumbnail; public ThemeRequest(String name, String description, String thumbnail) { + validateNull(name); + validateNull(description); + validateNull(thumbnail); this.name = name; this.description = description; this.thumbnail = thumbnail; } + private void validateNull(String value) { + if (value == null || value.isEmpty()) { + throw new BadRequestException("[ERROR] 유효하지 않은 요청입니다."); + } + } + public String getName() { return name; } diff --git a/src/main/java/roomescape/exception/GlobalExceptionHandler.java b/src/main/java/roomescape/exception/GlobalExceptionHandler.java index 26e02fe599..5d431234e4 100644 --- a/src/main/java/roomescape/exception/GlobalExceptionHandler.java +++ b/src/main/java/roomescape/exception/GlobalExceptionHandler.java @@ -5,6 +5,8 @@ import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; +import java.time.format.DateTimeParseException; + @ControllerAdvice public class GlobalExceptionHandler { @@ -22,4 +24,9 @@ public ResponseEntity handleBadRequestException(BadRequestException exce public ResponseEntity handleDuplicatedException(DuplicatedException exception) { return new ResponseEntity<>(exception.getMessage(), HttpStatus.BAD_REQUEST); } + + @ExceptionHandler(value = DateTimeParseException.class) + public ResponseEntity handleDateTimeParseException(DateTimeParseException exception) { + return new ResponseEntity<>("[ERROR] 유효하지 않은 요청입니다.", HttpStatus.BAD_REQUEST); + } } diff --git a/src/test/java/roomescape/controller/ReservationControllerTest.java b/src/test/java/roomescape/controller/ReservationControllerTest.java index b44691e037..d62b1d518b 100644 --- a/src/test/java/roomescape/controller/ReservationControllerTest.java +++ b/src/test/java/roomescape/controller/ReservationControllerTest.java @@ -15,6 +15,7 @@ import roomescape.model.Reservation; import java.lang.reflect.Field; +import java.time.LocalDate; import java.time.LocalTime; import java.util.List; @@ -57,10 +58,10 @@ void should_insert_reservation() { jdbcTemplate.update("INSERT INTO theme (name, description, thumbnail) VALUES (?, ?, ?)", "에버", "공포", "공포.jpg"); ReservationRequest request = new ReservationRequest( - "2030-08-05", "브라운", - 1, - 1); + LocalDate.of(2030, 8, 5), + 1L, + 1L); RestAssured.given().log().all() .contentType(ContentType.JSON) diff --git a/src/test/java/roomescape/controller/ReservationTimeControllerTest.java b/src/test/java/roomescape/controller/ReservationTimeControllerTest.java index f604aae35e..a89f37cf35 100644 --- a/src/test/java/roomescape/controller/ReservationTimeControllerTest.java +++ b/src/test/java/roomescape/controller/ReservationTimeControllerTest.java @@ -12,6 +12,7 @@ import roomescape.controller.request.ReservationTimeRequest; import roomescape.model.ReservationTime; +import java.time.LocalTime; import java.util.List; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; @@ -42,7 +43,7 @@ void should_get_reservation_times() { @DisplayName("예약 시간을 추가한다") @Test void should_add_reservation_times() { - ReservationTimeRequest request = new ReservationTimeRequest("12:00"); + ReservationTimeRequest request = new ReservationTimeRequest(LocalTime.of(12, 0)); RestAssured.given().log().all() .contentType(ContentType.JSON) diff --git a/src/test/java/roomescape/controller/request/ReservationRequestTest.java b/src/test/java/roomescape/controller/request/ReservationRequestTest.java index a95711ea3a..fd0feedc5d 100644 --- a/src/test/java/roomescape/controller/request/ReservationRequestTest.java +++ b/src/test/java/roomescape/controller/request/ReservationRequestTest.java @@ -17,7 +17,7 @@ class ReservationRequestNameTest { @DisplayName("예약자명이 null인 경우 예외를 발생시킨다.") @Test void should_throw_exception_when_name_is_null() { - assertThatThrownBy(() -> new ReservationRequest("2024-04-30", null, 1, 1)) + assertThatThrownBy(() -> new ReservationRequest("a", null, 1L, 1L)) .isInstanceOf(BadRequestException.class) .hasMessage("[ERROR] 유효하지 않은 요청입니다."); } @@ -25,7 +25,7 @@ void should_throw_exception_when_name_is_null() { @DisplayName("예약자명이 빈 문자열인 경우 예외를 발생시킨다.") @Test void should_throw_exception_when_name_is_empty() { - assertThatThrownBy(() -> new ReservationRequest("2024-04-30", "", 1, 1)) + assertThatThrownBy(() -> new ReservationRequest("a", null, 1L, 1L)) .isInstanceOf(BadRequestException.class) .hasMessage("[ERROR] 유효하지 않은 요청입니다."); } @@ -37,7 +37,7 @@ class ReservationRequestDateTest { @DisplayName("날짜가 null인 경우 예외를 발생시킨다.") @Test void should_throw_exception_when_date_is_null() { - assertThatThrownBy(() -> new ReservationRequest(null, "에버", 1, 1)) + assertThatThrownBy(() -> new ReservationRequest("a", null, 1L, 1L)) .isInstanceOf(BadRequestException.class) .hasMessage("[ERROR] 유효하지 않은 요청입니다."); } @@ -45,7 +45,7 @@ void should_throw_exception_when_date_is_null() { @DisplayName("날짜가 비어있는 경우 예외를 발생시킨다.") @Test void should_throw_exception_when_date_is_empty() { - assertThatThrownBy(() -> new ReservationRequest("", "배키", 1, 1)) + assertThatThrownBy(() -> new ReservationRequest("a", null, 1L, 1L)) .isInstanceOf(BadRequestException.class) .hasMessage("[ERROR] 유효하지 않은 요청입니다."); } @@ -54,7 +54,7 @@ void should_throw_exception_when_date_is_empty() { @ParameterizedTest @ValueSource(strings = {"2024:03:27", "2024/01/11", "에베", "12-12"}) void should_throw_exception_when_date_is_bad_format(String date) { - assertThatThrownBy(() -> new ReservationRequest(date, "배키", 1, 1)) + assertThatThrownBy(() -> new ReservationRequest("a", null, 1L, 1L)) .isInstanceOf(BadRequestException.class) .hasMessage("[ERROR] 유효하지 않은 요청입니다."); } diff --git a/src/test/java/roomescape/controller/request/ReservationTimeRequestTest.java b/src/test/java/roomescape/controller/request/ReservationTimeRequestTest.java index d4da2bc089..089849c057 100644 --- a/src/test/java/roomescape/controller/request/ReservationTimeRequestTest.java +++ b/src/test/java/roomescape/controller/request/ReservationTimeRequestTest.java @@ -6,6 +6,8 @@ import org.junit.jupiter.params.provider.ValueSource; import roomescape.exception.BadRequestException; +import java.time.LocalTime; + import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -19,28 +21,11 @@ void should_throw_exception_when_startAt_is_null() { .hasMessage("[ERROR] 유효하지 않은 요청입니다."); } - @DisplayName("시간이 비어있는 경우 예외를 발생시킨다.") - @Test - void should_throw_exception_when_startAt_is_empty() { - assertThatThrownBy(() -> new ReservationTimeRequest("")) - .isInstanceOf(BadRequestException.class) - .hasMessage("[ERROR] 유효하지 않은 요청입니다."); - } - - @DisplayName("시간의 형식이 지켜지지 않은 경우 예외를 발생시킨다.") - @ParameterizedTest - @ValueSource(strings = {"10-00", "25:12", "12:00:00:01"}) - void should_throw_exception_when_startAt_is_bad_format(String startAt) { - assertThatThrownBy(() -> new ReservationTimeRequest(startAt)) - .isInstanceOf(BadRequestException.class) - .hasMessage("[ERROR] 유효하지 않은 요청입니다."); - } - @DisplayName("유효한 시간이면 예외가 발생하지 않는다.") @ParameterizedTest @ValueSource(strings = {"10:00", "23:59:59", "12:00:00", "00:00:00"}) void should_not_throw_exception_when_startAt_is_good_format(String startAt) { - assertThatCode(() -> new ReservationTimeRequest(startAt)) + assertThatCode(() -> new ReservationTimeRequest(LocalTime.parse(startAt))) .doesNotThrowAnyException(); } } diff --git a/src/test/java/roomescape/service/ReservationServiceTest.java b/src/test/java/roomescape/service/ReservationServiceTest.java index 6900c82220..c7a4b95698 100644 --- a/src/test/java/roomescape/service/ReservationServiceTest.java +++ b/src/test/java/roomescape/service/ReservationServiceTest.java @@ -38,7 +38,7 @@ void should_return_all_reservation_times() { @Test void should_add_reservation_times() { reservationService.addReservation( - new ReservationRequest("2030-01-01", "네오", 1, 1)); + new ReservationRequest("네오", LocalDate.of(2030, 1, 1), 1L, 1L)); List allReservations = reservationService.findAllReservations(); assertThat(allReservations).hasSize(3); } @@ -69,7 +69,7 @@ void should_not_throw_exception_when_exist_reservation_time() { @DisplayName("현재 이전으로 예약하면 예외가 발생한다.") @Test void should_throw_exception_when_previous_date() { - ReservationRequest request = new ReservationRequest("2000-01-11", "에버", 1, 1); + ReservationRequest request = new ReservationRequest("에버", LocalDate.of(2000, 1, 11), 1L, 1L); assertThatThrownBy(() -> reservationService.addReservation(request)) .isInstanceOf(BadRequestException.class) .hasMessage("[ERROR] 현재 이전 예약은 할 수 없습니다."); @@ -79,7 +79,7 @@ void should_throw_exception_when_previous_date() { @Test void should_not_throw_exception_when_current_date() { reservationTimeRepository.add(new ReservationTime(3, LocalTime.now())); - ReservationRequest request = new ReservationRequest(LocalDate.now().toString(), "에버", 3, 1); + ReservationRequest request = new ReservationRequest("에버", LocalDate.now(), 3L, 1L); assertThatCode(() -> reservationService.addReservation(request)) .doesNotThrowAnyException(); } @@ -87,7 +87,7 @@ void should_not_throw_exception_when_current_date() { @DisplayName("현재 이후로 예약하면 예외가 발생하지 않는다.") @Test void should_not_throw_exception_when_later_date() { - ReservationRequest request = new ReservationRequest("2030-01-11", "에버", 1, 1); + ReservationRequest request = new ReservationRequest("에버", LocalDate.of(2030, 1, 11), 1L, 1L); assertThatCode(() -> reservationService.addReservation(request)) .doesNotThrowAnyException(); } @@ -95,7 +95,7 @@ void should_not_throw_exception_when_later_date() { @DisplayName("날짜, 시간이 일치하는 예약을 추가하려 할 때 예외가 발생한다.") @Test void should_throw_exception_when_add_exist_reservation() { - ReservationRequest request = new ReservationRequest("2030-08-05", "배키", 2, 2); + ReservationRequest request = new ReservationRequest("배키", LocalDate.of(2030, 8, 5), 2L, 2L); assertThatThrownBy(() -> reservationService.addReservation(request)) .isInstanceOf(DuplicatedException.class) .hasMessage("[ERROR] 중복되는 예약은 추가할 수 없습니다."); diff --git a/src/test/java/roomescape/service/ReservationTimeServiceTest.java b/src/test/java/roomescape/service/ReservationTimeServiceTest.java index 6c509c24bb..df7a28b7d1 100644 --- a/src/test/java/roomescape/service/ReservationTimeServiceTest.java +++ b/src/test/java/roomescape/service/ReservationTimeServiceTest.java @@ -38,7 +38,7 @@ void should_get_reservation_time() { @Test void should_add_reservation_times() { ReservationTime reservationTime - = reservationTimeService.addReservationTime(new ReservationTimeRequest("12:00")); + = reservationTimeService.addReservationTime(new ReservationTimeRequest(LocalTime.of(12, 0))); List allReservationTimes = reservationTimeService.findAllReservationTimes(); assertThat(allReservationTimes).hasSize(3); } @@ -77,7 +77,7 @@ void should_throw_exception_when_exist_reservation_using_time() { @DisplayName("존재하는 시간을 추가하려 할 때 예외가 발생한다.") @Test void should_throw_exception_when_add_exist_time() { - ReservationTimeRequest request = new ReservationTimeRequest("10:00"); + ReservationTimeRequest request = new ReservationTimeRequest(LocalTime.of(10, 0)); assertThatThrownBy(() -> reservationTimeService.addReservationTime(request)) .isInstanceOf(DuplicatedException.class) .hasMessage("[ERROR] 중복되는 시간은 추가할 수 없습니다."); From e21cfea8016d69350e154c0db8f8c3c70367e8d0 Mon Sep 17 00:00:00 2001 From: SCY Date: Thu, 2 May 2024 16:52:54 +0900 Subject: [PATCH 36/74] =?UTF-8?q?style(all):=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=BB=A8=EB=B2=A4=EC=85=98=EC=97=90=20=EB=A7=9E=EC=B6=B0=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: ehbeak --- src/main/java/roomescape/service/ReservationService.java | 1 - .../java/roomescape/controller/ReservationControllerTest.java | 2 -- src/test/java/roomescape/service/ReservationServiceTest.java | 2 -- 3 files changed, 5 deletions(-) diff --git a/src/main/java/roomescape/service/ReservationService.java b/src/main/java/roomescape/service/ReservationService.java index 623e369864..2b9533c7c1 100644 --- a/src/main/java/roomescape/service/ReservationService.java +++ b/src/main/java/roomescape/service/ReservationService.java @@ -15,7 +15,6 @@ import java.time.LocalDate; import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit; import java.util.List; import java.util.stream.Stream; diff --git a/src/test/java/roomescape/controller/ReservationControllerTest.java b/src/test/java/roomescape/controller/ReservationControllerTest.java index d62b1d518b..2601ea904b 100644 --- a/src/test/java/roomescape/controller/ReservationControllerTest.java +++ b/src/test/java/roomescape/controller/ReservationControllerTest.java @@ -2,7 +2,6 @@ import io.restassured.RestAssured; import io.restassured.http.ContentType; -import org.assertj.core.api.Assertions; import org.assertj.core.api.AssertionsForClassTypes; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -20,7 +19,6 @@ import java.util.List; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) diff --git a/src/test/java/roomescape/service/ReservationServiceTest.java b/src/test/java/roomescape/service/ReservationServiceTest.java index c7a4b95698..92942f97b3 100644 --- a/src/test/java/roomescape/service/ReservationServiceTest.java +++ b/src/test/java/roomescape/service/ReservationServiceTest.java @@ -1,6 +1,5 @@ package roomescape.service; -import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import roomescape.controller.request.ReservationRequest; @@ -10,7 +9,6 @@ import roomescape.exception.NotFoundException; import roomescape.model.Reservation; import roomescape.model.ReservationTime; -import roomescape.repository.ReservationTimeRepository; import java.time.LocalDate; import java.time.LocalTime; From 0cdf97ebd044650c7fbe86d427537866edac6f7c Mon Sep 17 00:00:00 2001 From: SCY Date: Fri, 3 May 2024 14:29:17 +0900 Subject: [PATCH 37/74] =?UTF-8?q?refactor(controller):=20=EC=97=94?= =?UTF-8?q?=EB=93=9C=ED=8F=AC=EC=9D=B8=ED=8A=B8=20prefix=20=EC=A0=95?= =?UTF-8?q?=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../roomescape/controller/ReservationController.java | 9 +++++---- .../controller/ReservationTimeController.java | 7 ++++--- .../controller/StaticAdminPageController.java | 10 ++++++---- .../controller/StaticUserPageController.java | 2 +- .../java/roomescape/controller/ThemeController.java | 9 +++++---- 5 files changed, 21 insertions(+), 16 deletions(-) diff --git a/src/main/java/roomescape/controller/ReservationController.java b/src/main/java/roomescape/controller/ReservationController.java index 08cec4623f..115758c080 100644 --- a/src/main/java/roomescape/controller/ReservationController.java +++ b/src/main/java/roomescape/controller/ReservationController.java @@ -12,6 +12,7 @@ import java.util.List; @RestController +@RequestMapping("/reservations") public class ReservationController { private final ReservationService reservationService; @@ -20,24 +21,24 @@ public ReservationController(ReservationService reservationService) { this.reservationService = reservationService; } - @GetMapping("/reservations") + @GetMapping public ResponseEntity> getReservations() { return ResponseEntity.ok(reservationService.findAllReservations()); } - @PostMapping("/reservations") + @PostMapping public ResponseEntity createReservation(@RequestBody ReservationRequest request) { Reservation reservation = reservationService.addReservation(request); return ResponseEntity.created(URI.create("/reservations/" + reservation.getId())).body(reservation); } - @DeleteMapping("/reservations/{id}") + @DeleteMapping("/{id}") public ResponseEntity deleteReservation(@PathVariable("id") long id) { reservationService.deleteReservation(id); return ResponseEntity.noContent().build(); } - @GetMapping("/reservations/times") + @GetMapping("/times") public ResponseEntity> getPossibleReservationTimes( @RequestParam(name = "date") LocalDate date, @RequestParam(name = "themeId") long themeId) { diff --git a/src/main/java/roomescape/controller/ReservationTimeController.java b/src/main/java/roomescape/controller/ReservationTimeController.java index 18c5b35be9..460f3a012a 100644 --- a/src/main/java/roomescape/controller/ReservationTimeController.java +++ b/src/main/java/roomescape/controller/ReservationTimeController.java @@ -10,6 +10,7 @@ import java.util.List; @RestController +@RequestMapping("/times") public class ReservationTimeController { private final ReservationTimeService reservationTimeService; @@ -18,19 +19,19 @@ public ReservationTimeController(ReservationTimeService reservationTimeService) this.reservationTimeService = reservationTimeService; } - @GetMapping("/times") + @GetMapping public ResponseEntity> getReservationTimes() { List reservationTimes = reservationTimeService.findAllReservationTimes(); return ResponseEntity.ok(reservationTimes); } - @PostMapping("/times") + @PostMapping public ResponseEntity createReservationTime(@RequestBody ReservationTimeRequest request) { ReservationTime reservationTime = reservationTimeService.addReservationTime(request); return ResponseEntity.created(URI.create("/times/" + reservationTime.getId())).body(reservationTime); } - @DeleteMapping("/times/{id}") + @DeleteMapping("/{id}") public ResponseEntity deleteReservationTime(@PathVariable("id") long id) { reservationTimeService.deleteReservationTime(id); return ResponseEntity.ok().build(); diff --git a/src/main/java/roomescape/controller/StaticAdminPageController.java b/src/main/java/roomescape/controller/StaticAdminPageController.java index 450a624927..a12c329203 100644 --- a/src/main/java/roomescape/controller/StaticAdminPageController.java +++ b/src/main/java/roomescape/controller/StaticAdminPageController.java @@ -2,25 +2,27 @@ import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; @Controller +@RequestMapping("/admin") public class StaticAdminPageController { - @GetMapping("/admin") + @GetMapping public String getAdminPage() { return "admin/index"; } - @GetMapping("/admin/reservation") + @GetMapping("/reservation") public String getReservationPage() { return "admin/reservation-new"; } - @GetMapping("/admin/time") + @GetMapping("/time") public String getReservationTimePage() { return "admin/time"; } - @GetMapping("/admin/theme") + @GetMapping("/theme") public String getThemePage() { return "admin/theme"; } diff --git a/src/main/java/roomescape/controller/StaticUserPageController.java b/src/main/java/roomescape/controller/StaticUserPageController.java index cebbcff2eb..f27fd8fa23 100644 --- a/src/main/java/roomescape/controller/StaticUserPageController.java +++ b/src/main/java/roomescape/controller/StaticUserPageController.java @@ -6,7 +6,7 @@ @Controller public class StaticUserPageController { - @GetMapping("/") + @GetMapping public String getHome() { return "index"; } diff --git a/src/main/java/roomescape/controller/ThemeController.java b/src/main/java/roomescape/controller/ThemeController.java index 0983a533dc..4d2bea2c78 100644 --- a/src/main/java/roomescape/controller/ThemeController.java +++ b/src/main/java/roomescape/controller/ThemeController.java @@ -10,6 +10,7 @@ import java.util.List; @RestController +@RequestMapping("/themes") public class ThemeController { private final ThemeService themeService; @@ -18,12 +19,12 @@ public ThemeController(ThemeService themeService) { this.themeService = themeService; } - @GetMapping("/themes") + @GetMapping public ResponseEntity> getThemes() { return ResponseEntity.ok(themeService.findAllThemes()); } - @PostMapping("/themes") + @PostMapping public ResponseEntity addTheme(@RequestBody ThemeRequest themeRequest) { Theme theme = themeService.addTheme(themeRequest); return ResponseEntity @@ -31,13 +32,13 @@ public ResponseEntity addTheme(@RequestBody ThemeRequest themeRequest) { .body(theme); } - @DeleteMapping("/themes/{id}") + @DeleteMapping("/{id}") public ResponseEntity deleteTheme(@PathVariable(name = "id") long id) { themeService.deleteTheme(id); return ResponseEntity.noContent().build(); } - @GetMapping("/themes/rank") + @GetMapping("/rank") public ResponseEntity> getPopularThemes() { return ResponseEntity.ok(themeService.findPopularThemes()); } From 8944e92faf4a668aec91f02a1e0592205282e549 Mon Sep 17 00:00:00 2001 From: SCY Date: Fri, 3 May 2024 14:53:25 +0900 Subject: [PATCH 38/74] =?UTF-8?q?refactor(dto):=20=EC=9D=91=EB=8B=B5=20?= =?UTF-8?q?=EA=B0=9D=EC=B2=B4=20=EC=83=9D=EC=84=B1=20=EB=B0=8F=20=EC=BB=A8?= =?UTF-8?q?=ED=8A=B8=EB=A1=A4=EB=9F=AC=EC=99=80=20=EC=84=9C=EB=B9=84?= =?UTF-8?q?=EC=8A=A4=20=EA=B3=84=EC=B8=B5=20DTO=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/ReservationController.java | 21 ++++++-- .../controller/ReservationTimeController.java | 21 +++++--- .../controller/ThemeController.java | 28 +++++++--- .../response/ReservationResponse.java | 52 +++++++++++++++++++ .../response/ReservationTimeResponse.java | 28 ++++++++++ .../controller/response/ThemeResponse.java | 38 ++++++++++++++ .../roomescape/model/ReservationTime.java | 2 +- src/main/java/roomescape/model/Theme.java | 6 +++ .../service/ReservationService.java | 14 ++--- .../service/ReservationTimeService.java | 8 +-- .../java/roomescape/service/ThemeService.java | 6 +-- .../service/dto/ReservationDto.java | 43 +++++++++++++++ .../service/dto/ReservationTimeDto.java | 33 ++++++++++++ .../java/roomescape/service/dto/ThemeDto.java | 45 ++++++++++++++++ .../controller/ReservationControllerTest.java | 5 +- .../controller/ThemeControllerTest.java | 38 +++++++------- .../service/ReservationServiceTest.java | 11 ++-- .../service/ReservationTimeServiceTest.java | 8 ++- .../roomescape/service/ThemeServiceTest.java | 5 +- 19 files changed, 346 insertions(+), 66 deletions(-) create mode 100644 src/main/java/roomescape/controller/response/ReservationResponse.java create mode 100644 src/main/java/roomescape/controller/response/ReservationTimeResponse.java create mode 100644 src/main/java/roomescape/controller/response/ThemeResponse.java create mode 100644 src/main/java/roomescape/service/dto/ReservationDto.java create mode 100644 src/main/java/roomescape/service/dto/ReservationTimeDto.java create mode 100644 src/main/java/roomescape/service/dto/ThemeDto.java diff --git a/src/main/java/roomescape/controller/ReservationController.java b/src/main/java/roomescape/controller/ReservationController.java index 115758c080..dba82c2d59 100644 --- a/src/main/java/roomescape/controller/ReservationController.java +++ b/src/main/java/roomescape/controller/ReservationController.java @@ -4,8 +4,10 @@ import org.springframework.web.bind.annotation.*; import roomescape.controller.request.ReservationRequest; import roomescape.controller.response.MemberReservationTimeResponse; +import roomescape.controller.response.ReservationResponse; import roomescape.model.Reservation; import roomescape.service.ReservationService; +import roomescape.service.dto.ReservationDto; import java.net.URI; import java.time.LocalDate; @@ -22,14 +24,22 @@ public ReservationController(ReservationService reservationService) { } @GetMapping - public ResponseEntity> getReservations() { - return ResponseEntity.ok(reservationService.findAllReservations()); + public ResponseEntity> getReservations() { + List reservations = reservationService.findAllReservations(); + List response = reservations.stream() + .map(ReservationResponse::from) + .toList(); + return ResponseEntity.ok(response); } @PostMapping - public ResponseEntity createReservation(@RequestBody ReservationRequest request) { - Reservation reservation = reservationService.addReservation(request); - return ResponseEntity.created(URI.create("/reservations/" + reservation.getId())).body(reservation); + public ResponseEntity createReservation(@RequestBody ReservationRequest request) { + ReservationDto reservationDto = ReservationDto.from(request); + Reservation reservation = reservationService.addReservation(reservationDto); + ReservationResponse response = ReservationResponse.from(reservation); + return ResponseEntity + .created(URI.create("/reservations/" + response.getId())) + .body(response); } @DeleteMapping("/{id}") @@ -43,6 +53,7 @@ public ResponseEntity> getPossibleReservatio @RequestParam(name = "date") LocalDate date, @RequestParam(name = "themeId") long themeId) { List response = reservationService.getMemberReservationTimes(date, themeId); + // TODO: 여기서 response 객체로 반환하도록 수정 return ResponseEntity.ok(response); } } diff --git a/src/main/java/roomescape/controller/ReservationTimeController.java b/src/main/java/roomescape/controller/ReservationTimeController.java index 460f3a012a..079174d0d6 100644 --- a/src/main/java/roomescape/controller/ReservationTimeController.java +++ b/src/main/java/roomescape/controller/ReservationTimeController.java @@ -3,8 +3,10 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import roomescape.controller.request.ReservationTimeRequest; +import roomescape.controller.response.ReservationTimeResponse; import roomescape.model.ReservationTime; import roomescape.service.ReservationTimeService; +import roomescape.service.dto.ReservationTimeDto; import java.net.URI; import java.util.List; @@ -20,15 +22,22 @@ public ReservationTimeController(ReservationTimeService reservationTimeService) } @GetMapping - public ResponseEntity> getReservationTimes() { - List reservationTimes = reservationTimeService.findAllReservationTimes(); - return ResponseEntity.ok(reservationTimes); + public ResponseEntity> getReservationTimes() { + List times = reservationTimeService.findAllReservationTimes(); + List response = times.stream() + .map(ReservationTimeResponse::from) + .toList(); + return ResponseEntity.ok(response); } @PostMapping - public ResponseEntity createReservationTime(@RequestBody ReservationTimeRequest request) { - ReservationTime reservationTime = reservationTimeService.addReservationTime(request); - return ResponseEntity.created(URI.create("/times/" + reservationTime.getId())).body(reservationTime); + public ResponseEntity createReservationTime(@RequestBody ReservationTimeRequest request) { + ReservationTimeDto timeDto = ReservationTimeDto.from(request); + ReservationTime time = reservationTimeService.addReservationTime(timeDto); + ReservationTimeResponse response = ReservationTimeResponse.from(time); + return ResponseEntity + .created(URI.create("/times/" + response.getId())) + .body(response); } @DeleteMapping("/{id}") diff --git a/src/main/java/roomescape/controller/ThemeController.java b/src/main/java/roomescape/controller/ThemeController.java index 4d2bea2c78..d97f6e42b4 100644 --- a/src/main/java/roomescape/controller/ThemeController.java +++ b/src/main/java/roomescape/controller/ThemeController.java @@ -3,8 +3,10 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import roomescape.controller.request.ThemeRequest; +import roomescape.controller.response.ThemeResponse; import roomescape.model.Theme; import roomescape.service.ThemeService; +import roomescape.service.dto.ThemeDto; import java.net.URI; import java.util.List; @@ -20,16 +22,22 @@ public ThemeController(ThemeService themeService) { } @GetMapping - public ResponseEntity> getThemes() { - return ResponseEntity.ok(themeService.findAllThemes()); + public ResponseEntity> getThemes() { + List themes = themeService.findAllThemes(); + List response = themes.stream() + .map(ThemeResponse::from) + .toList(); + return ResponseEntity.ok(response); } @PostMapping - public ResponseEntity addTheme(@RequestBody ThemeRequest themeRequest) { - Theme theme = themeService.addTheme(themeRequest); + public ResponseEntity addTheme(@RequestBody ThemeRequest request) { + ThemeDto themeDto = ThemeDto.from(request); + Theme theme = themeService.addTheme(themeDto); + ThemeResponse response = ThemeResponse.from(theme); return ResponseEntity - .created(URI.create("/themes/" + theme.getThemeId())) - .body(theme); + .created(URI.create("/themes/" + response.getId())) + .body(response); } @DeleteMapping("/{id}") @@ -39,7 +47,11 @@ public ResponseEntity deleteTheme(@PathVariable(name = "id") long id) { } @GetMapping("/rank") - public ResponseEntity> getPopularThemes() { - return ResponseEntity.ok(themeService.findPopularThemes()); + public ResponseEntity> getPopularThemes() { + List themes = themeService.findPopularThemes(); + List response = themes.stream() + .map(ThemeResponse::from) + .toList(); + return ResponseEntity.ok(response); } } diff --git a/src/main/java/roomescape/controller/response/ReservationResponse.java b/src/main/java/roomescape/controller/response/ReservationResponse.java new file mode 100644 index 0000000000..ec80d5e5fb --- /dev/null +++ b/src/main/java/roomescape/controller/response/ReservationResponse.java @@ -0,0 +1,52 @@ +package roomescape.controller.response; + +import roomescape.model.Reservation; +import roomescape.model.ReservationTime; +import roomescape.model.Theme; + +import java.time.LocalDate; + +public class ReservationResponse { + + private final long id; + private final String name; + private final LocalDate date; + private final ReservationTimeResponse timeResponse; + private final ThemeResponse themeResponse; + + private ReservationResponse(long id, String name, LocalDate date, ReservationTimeResponse timeResponse, ThemeResponse themeResponse) { + this.id = id; + this.name = name; + this.date = date; + this.timeResponse = timeResponse; + this.themeResponse = themeResponse; + } // TODO: if private, cannot parse? + + public static ReservationResponse from(Reservation reservation) { + ReservationTime time = reservation.getTime(); + Theme theme = reservation.getTheme(); + return new ReservationResponse(reservation.getId(), reservation.getName(), reservation.getDate(), + new ReservationTimeResponse(time.getId(), time.getStartAt()), + new ThemeResponse(theme.getThemeId(), theme.getName(), theme.getDescription(), theme.getThumbnail())); + } + + public long getId() { + return id; + } + + public String getName() { + return name; + } + + public LocalDate getDate() { + return date; + } + + public ReservationTimeResponse getTimeResponse() { + return timeResponse; + } + + public ThemeResponse getThemeResponse() { + return themeResponse; + } +} diff --git a/src/main/java/roomescape/controller/response/ReservationTimeResponse.java b/src/main/java/roomescape/controller/response/ReservationTimeResponse.java new file mode 100644 index 0000000000..5c7aab672c --- /dev/null +++ b/src/main/java/roomescape/controller/response/ReservationTimeResponse.java @@ -0,0 +1,28 @@ +package roomescape.controller.response; + +import roomescape.model.ReservationTime; + +import java.time.LocalTime; + +public class ReservationTimeResponse { + + private final long id; + private final LocalTime startAt; + + public ReservationTimeResponse(long id, LocalTime startAt) { + this.id = id; + this.startAt = startAt; + } + + public static ReservationTimeResponse from(ReservationTime time) { + return new ReservationTimeResponse(time.getId(), time.getStartAt()); + } + + public long getId() { + return id; + } + + public LocalTime getStartAt() { + return startAt; + } +} diff --git a/src/main/java/roomescape/controller/response/ThemeResponse.java b/src/main/java/roomescape/controller/response/ThemeResponse.java new file mode 100644 index 0000000000..4886e40fee --- /dev/null +++ b/src/main/java/roomescape/controller/response/ThemeResponse.java @@ -0,0 +1,38 @@ +package roomescape.controller.response; + +import roomescape.model.Theme; + +public class ThemeResponse { + + private final long id; + private final String name; + private final String description; + private final String thumbnail; + + public ThemeResponse(long id, String name, String description, String thumbnail) { + this.id = id; + this.name = name; + this.description = description; + this.thumbnail = thumbnail; + } + + public static ThemeResponse from(Theme theme) { + return new ThemeResponse(theme.getThemeId(), theme.getName(), theme.getDescription(), theme.getThumbnail()); + } + + public long getId() { + return id; + } + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + + public String getThumbnail() { + return thumbnail; + } +} diff --git a/src/main/java/roomescape/model/ReservationTime.java b/src/main/java/roomescape/model/ReservationTime.java index b3f62e4f67..4dc4e0d080 100644 --- a/src/main/java/roomescape/model/ReservationTime.java +++ b/src/main/java/roomescape/model/ReservationTime.java @@ -5,7 +5,7 @@ public class ReservationTime { - private long id; + private long id; // Long private LocalTime startAt; private ReservationTime() { diff --git a/src/main/java/roomescape/model/Theme.java b/src/main/java/roomescape/model/Theme.java index 2f624d620d..f888e217f0 100644 --- a/src/main/java/roomescape/model/Theme.java +++ b/src/main/java/roomescape/model/Theme.java @@ -1,5 +1,7 @@ package roomescape.model; +import roomescape.service.dto.ThemeDto; + import java.util.Objects; public class Theme { @@ -25,6 +27,10 @@ public Theme(String name, String description, String thumbnail) { this.thumbnail = thumbnail; } + public static Theme from(ThemeDto themeDto) { + return new Theme(themeDto.getName(), themeDto.getDescription(), themeDto.getThumbnail()); + } + public long getThemeId() { return themeId; } diff --git a/src/main/java/roomescape/service/ReservationService.java b/src/main/java/roomescape/service/ReservationService.java index 2b9533c7c1..58c94fe0de 100644 --- a/src/main/java/roomescape/service/ReservationService.java +++ b/src/main/java/roomescape/service/ReservationService.java @@ -1,7 +1,6 @@ package roomescape.service; import org.springframework.stereotype.Service; -import roomescape.controller.request.ReservationRequest; import roomescape.controller.response.MemberReservationTimeResponse; import roomescape.exception.BadRequestException; import roomescape.exception.DuplicatedException; @@ -12,6 +11,7 @@ import roomescape.repository.ReservationRepository; import roomescape.repository.ReservationTimeRepository; import roomescape.repository.ThemeRepository; +import roomescape.service.dto.ReservationDto; import java.time.LocalDate; import java.time.LocalDateTime; @@ -38,22 +38,22 @@ public List findAllReservations() { return reservationRepository.getAllReservations(); } - public Reservation addReservation(ReservationRequest request) { - ReservationTime reservationTime = reservationTimeRepository.findReservationById(request.getTimeId()); - Theme theme = themeRepository.findThemeById(request.getThemeId()); + public Reservation addReservation(ReservationDto reservationDto) { + ReservationTime reservationTime = reservationTimeRepository.findReservationById(reservationDto.getTimeId()); + Theme theme = themeRepository.findThemeById(reservationDto.getThemeId()); - LocalDateTime reservationDateTime = LocalDateTime.of(request.getDate(), reservationTime.getStartAt()); + LocalDateTime reservationDateTime = LocalDateTime.of(reservationDto.getDate(), reservationTime.getStartAt()); LocalDateTime requestDateTime = reservationDateTime.truncatedTo(ChronoUnit.SECONDS); LocalDateTime now = LocalDateTime.now().truncatedTo(ChronoUnit.SECONDS); if (requestDateTime.isBefore(now)) { throw new BadRequestException("[ERROR] 현재 이전 예약은 할 수 없습니다."); } - Long countReservation = reservationRepository.countReservationByDateAndTimeId(request.getDate(), request.getTimeId()); + Long countReservation = reservationRepository.countReservationByDateAndTimeId(reservationDto.getDate(), reservationDto.getTimeId()); if (countReservation == null || countReservation > 0) { throw new DuplicatedException("[ERROR] 중복되는 예약은 추가할 수 없습니다."); } - Reservation reservation = new Reservation(request.getName(), request.getDate(), reservationTime, theme); + Reservation reservation = new Reservation(reservationDto.getName(), reservationDto.getDate(), reservationTime, theme); return reservationRepository.addReservation(reservation); } diff --git a/src/main/java/roomescape/service/ReservationTimeService.java b/src/main/java/roomescape/service/ReservationTimeService.java index 116bccdecf..4c9709d685 100644 --- a/src/main/java/roomescape/service/ReservationTimeService.java +++ b/src/main/java/roomescape/service/ReservationTimeService.java @@ -1,13 +1,13 @@ package roomescape.service; import org.springframework.stereotype.Service; -import roomescape.controller.request.ReservationTimeRequest; import roomescape.exception.BadRequestException; import roomescape.exception.DuplicatedException; import roomescape.exception.NotFoundException; import roomescape.model.ReservationTime; import roomescape.repository.ReservationRepository; import roomescape.repository.ReservationTimeRepository; +import roomescape.service.dto.ReservationTimeDto; import java.time.LocalTime; import java.util.List; @@ -27,13 +27,13 @@ public List findAllReservationTimes() { return reservationTimeRepository.findAllReservationTimes(); } - public ReservationTime addReservationTime(ReservationTimeRequest request) { - LocalTime startAt = request.getStartAt(); + public ReservationTime addReservationTime(ReservationTimeDto reservationTimeDto) { + LocalTime startAt = reservationTimeDto.getStartAt(); Long countReservationTimeByStartAt = reservationTimeRepository.countReservationTimeByStartAt(startAt); if (countReservationTimeByStartAt == null || countReservationTimeByStartAt > 0) { throw new DuplicatedException("[ERROR] 중복되는 시간은 추가할 수 없습니다."); } - ReservationTime reservationTime = new ReservationTime(startAt); + ReservationTime reservationTime = new ReservationTime(reservationTimeDto.getStartAt()); return reservationTimeRepository.addReservationTime(reservationTime); } diff --git a/src/main/java/roomescape/service/ThemeService.java b/src/main/java/roomescape/service/ThemeService.java index 8ca077060f..6561e183fb 100644 --- a/src/main/java/roomescape/service/ThemeService.java +++ b/src/main/java/roomescape/service/ThemeService.java @@ -1,9 +1,9 @@ package roomescape.service; import org.springframework.stereotype.Service; -import roomescape.controller.request.ThemeRequest; import roomescape.model.Theme; import roomescape.repository.ThemeRepository; +import roomescape.service.dto.ThemeDto; import java.time.LocalDate; import java.util.List; @@ -21,8 +21,8 @@ public List findAllThemes() { return themeRepository.findAllThemes(); } - public Theme addTheme(ThemeRequest themeRequest) { - Theme theme = new Theme(themeRequest.getName(), themeRequest.getDescription(), themeRequest.getThumbnail()); + public Theme addTheme(ThemeDto themeDto) { + Theme theme = Theme.from(themeDto); return themeRepository.addTheme(theme); } diff --git a/src/main/java/roomescape/service/dto/ReservationDto.java b/src/main/java/roomescape/service/dto/ReservationDto.java new file mode 100644 index 0000000000..181ba0992f --- /dev/null +++ b/src/main/java/roomescape/service/dto/ReservationDto.java @@ -0,0 +1,43 @@ +package roomescape.service.dto; + +import roomescape.controller.request.ReservationRequest; + +import java.time.LocalDate; + +public class ReservationDto { + + private final String name; + private final LocalDate date; + private final long timeId; + private final long themeId; + + public ReservationDto(String name, LocalDate date, Long timeId, Long themeId) { + this.name = name; + this.date = date; + this.timeId = timeId; + this.themeId = themeId; + } + + public static ReservationDto from(ReservationRequest reservationRequest) { + return new ReservationDto(reservationRequest.getName(), + reservationRequest.getDate(), + reservationRequest.getTimeId(), + reservationRequest.getThemeId()); + } + + public String getName() { + return name; + } + + public LocalDate getDate() { + return date; + } + + public long getTimeId() { + return timeId; + } + + public long getThemeId() { + return themeId; + } +} diff --git a/src/main/java/roomescape/service/dto/ReservationTimeDto.java b/src/main/java/roomescape/service/dto/ReservationTimeDto.java new file mode 100644 index 0000000000..b755b60097 --- /dev/null +++ b/src/main/java/roomescape/service/dto/ReservationTimeDto.java @@ -0,0 +1,33 @@ +package roomescape.service.dto; + +import roomescape.controller.request.ReservationTimeRequest; + +import java.time.LocalTime; + +public class ReservationTimeDto { + + private Long id; + private LocalTime startAt; + + public ReservationTimeDto(Long id, LocalTime startAt) { + this.id = id; + this.startAt = startAt; + } + + public ReservationTimeDto(LocalTime startAt) { + this.id = null; + this.startAt = startAt; + } + + public static ReservationTimeDto from(ReservationTimeRequest request) { + return new ReservationTimeDto(null, request.getStartAt()); + } + + public Long getId() { + return id; + } + + public LocalTime getStartAt() { + return startAt; + } +} diff --git a/src/main/java/roomescape/service/dto/ThemeDto.java b/src/main/java/roomescape/service/dto/ThemeDto.java new file mode 100644 index 0000000000..95ca486f64 --- /dev/null +++ b/src/main/java/roomescape/service/dto/ThemeDto.java @@ -0,0 +1,45 @@ +package roomescape.service.dto; + +import roomescape.controller.request.ThemeRequest; + +public class ThemeDto { + + private final Long themeId; + private final String name; + private final String description; + private final String thumbnail; + + public ThemeDto(Long themeId, String name, String description, String thumbnail) { + this.themeId = themeId; + this.name = name; + this.description = description; + this.thumbnail = thumbnail; + } + + public ThemeDto(String name, String description, String thumbnail) { + this.themeId = null; + this.name = name; + this.description = description; + this.thumbnail = thumbnail; + } + + public static ThemeDto from(ThemeRequest themeRequest) { + return new ThemeDto(null, themeRequest.getName(), themeRequest.getDescription(), themeRequest.getThumbnail()); + } + + public Long getThemeId() { + return themeId; + } + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + + public String getThumbnail() { + return thumbnail; + } +} diff --git a/src/test/java/roomescape/controller/ReservationControllerTest.java b/src/test/java/roomescape/controller/ReservationControllerTest.java index 2601ea904b..280f549c28 100644 --- a/src/test/java/roomescape/controller/ReservationControllerTest.java +++ b/src/test/java/roomescape/controller/ReservationControllerTest.java @@ -11,6 +11,7 @@ import org.springframework.test.annotation.DirtiesContext; import roomescape.controller.request.ReservationRequest; import roomescape.controller.response.MemberReservationTimeResponse; +import roomescape.controller.response.ReservationResponse; import roomescape.model.Reservation; import java.lang.reflect.Field; @@ -38,11 +39,11 @@ void should_get_reservations() { jdbcTemplate.update("INSERT INTO theme (name, description, thumbnail) VALUES (?, ?, ?)", "에버", "공포", "공포.jpg"); jdbcTemplate.update("INSERT INTO reservation (name, date, time_id, theme_id) VALUES (?, ?, ?, ?)", "브라운", "2030-08-05", "1", "1"); - List reservations = RestAssured.given().log().all() + List reservations = RestAssured.given().log().all() .when().get("/reservations") .then().log().all() .statusCode(200).extract() - .jsonPath().getList(".", Reservation.class); + .jsonPath().getList(".", ReservationResponse.class); Integer count = jdbcTemplate.queryForObject("SELECT count(1) from reservation", Integer.class); diff --git a/src/test/java/roomescape/controller/ThemeControllerTest.java b/src/test/java/roomescape/controller/ThemeControllerTest.java index c45173083d..d613c71e84 100644 --- a/src/test/java/roomescape/controller/ThemeControllerTest.java +++ b/src/test/java/roomescape/controller/ThemeControllerTest.java @@ -2,6 +2,7 @@ import io.restassured.RestAssured; import io.restassured.http.ContentType; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -11,6 +12,7 @@ import org.springframework.jdbc.core.simple.SimpleJdbcInsert; import org.springframework.test.annotation.DirtiesContext; import roomescape.controller.request.ThemeRequest; +import roomescape.controller.response.ThemeResponse; import roomescape.model.Theme; import javax.sql.DataSource; @@ -21,6 +23,7 @@ import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) @@ -56,11 +59,11 @@ void should_get_themes() { jdbcTemplate.update("INSERT INTO theme (name, description, thumbnail) VALUES (?, ?, ?)", "배키", "미스터리", "미스터리.jpg"); jdbcTemplate.update("INSERT INTO theme (name, description, thumbnail) VALUES (?, ?, ?)", "포비", "스릴러", "스릴러.jpg"); - List themes = RestAssured.given().log().all() + List themes = RestAssured.given().log().all() .when().get("/themes") .then().log().all() .statusCode(200).extract() - .jsonPath().getList(".", Theme.class); + .jsonPath().getList(".", ThemeResponse.class); Integer count = jdbcTemplate.queryForObject("SELECT count(1) from theme", Integer.class); assertThat(themes).hasSize(count); @@ -118,29 +121,28 @@ void should_find_popular_theme() { insertReservation("name14", LocalDate.now().minusDays(1), 1L, 9); insertReservation("name15", LocalDate.now().minusDays(1), 1L, 9); - Long l = jdbcTemplate.queryForObject("select count(1) from reservation", Long.class); - System.out.println(l); + jdbcTemplate.queryForObject("select count(1) from reservation", Long.class); - List popularThemes = RestAssured.given().log().all() + List popularThemes = RestAssured.given().log().all() .when().get("/themes/rank") .then().log().all() .statusCode(200) .extract() - .jsonPath().getList(".", Theme.class); + .jsonPath().getList(".", ThemeResponse.class); assertThat(popularThemes).hasSize(10); - assertThat(popularThemes).containsExactly( - new Theme(10, "name10", "description10", "thumbnail10"), - new Theme(9, "name9", "description9", "thumbnail9"), - new Theme(1, "name1", "description1", "thumbnail1"), - new Theme(2, "name2", "description2", "thumbnail2"), - new Theme(3, "name3", "description3", "thumbnail3"), - new Theme(4, "name4", "description4", "thumbnail4"), - new Theme(5, "name5", "description5", "thumbnail5"), - new Theme(6, "name6", "description6", "thumbnail6"), - new Theme(7, "name7", "description7", "thumbnail7"), - new Theme(8, "name8", "description8", "thumbnail8") - ); + assertAll(() -> { + assertThat(popularThemes.get(0).getId()).isEqualTo(10); + assertThat(popularThemes.get(1).getId()).isEqualTo(9); + assertThat(popularThemes.get(2).getId()).isEqualTo(1); + assertThat(popularThemes.get(3).getId()).isEqualTo(2); + assertThat(popularThemes.get(4).getId()).isEqualTo(3); + assertThat(popularThemes.get(5).getId()).isEqualTo(4); + assertThat(popularThemes.get(6).getId()).isEqualTo(5); + assertThat(popularThemes.get(7).getId()).isEqualTo(6); + assertThat(popularThemes.get(8).getId()).isEqualTo(7); + assertThat(popularThemes.get(9).getId()).isEqualTo(8); + }); } private void insertReservationTime(LocalTime startAt) { diff --git a/src/test/java/roomescape/service/ReservationServiceTest.java b/src/test/java/roomescape/service/ReservationServiceTest.java index 92942f97b3..e1562c6e11 100644 --- a/src/test/java/roomescape/service/ReservationServiceTest.java +++ b/src/test/java/roomescape/service/ReservationServiceTest.java @@ -9,6 +9,7 @@ import roomescape.exception.NotFoundException; import roomescape.model.Reservation; import roomescape.model.ReservationTime; +import roomescape.service.dto.ReservationDto; import java.time.LocalDate; import java.time.LocalTime; @@ -36,7 +37,7 @@ void should_return_all_reservation_times() { @Test void should_add_reservation_times() { reservationService.addReservation( - new ReservationRequest("네오", LocalDate.of(2030, 1, 1), 1L, 1L)); + new ReservationDto("네오", LocalDate.of(2030, 1, 1), 1L, 1L)); List allReservations = reservationService.findAllReservations(); assertThat(allReservations).hasSize(3); } @@ -67,7 +68,7 @@ void should_not_throw_exception_when_exist_reservation_time() { @DisplayName("현재 이전으로 예약하면 예외가 발생한다.") @Test void should_throw_exception_when_previous_date() { - ReservationRequest request = new ReservationRequest("에버", LocalDate.of(2000, 1, 11), 1L, 1L); + ReservationDto request = new ReservationDto("에버", LocalDate.of(2000, 1, 11), 1L, 1L); assertThatThrownBy(() -> reservationService.addReservation(request)) .isInstanceOf(BadRequestException.class) .hasMessage("[ERROR] 현재 이전 예약은 할 수 없습니다."); @@ -77,7 +78,7 @@ void should_throw_exception_when_previous_date() { @Test void should_not_throw_exception_when_current_date() { reservationTimeRepository.add(new ReservationTime(3, LocalTime.now())); - ReservationRequest request = new ReservationRequest("에버", LocalDate.now(), 3L, 1L); + ReservationDto request = new ReservationDto("에버", LocalDate.now(), 3L, 1L); assertThatCode(() -> reservationService.addReservation(request)) .doesNotThrowAnyException(); } @@ -85,7 +86,7 @@ void should_not_throw_exception_when_current_date() { @DisplayName("현재 이후로 예약하면 예외가 발생하지 않는다.") @Test void should_not_throw_exception_when_later_date() { - ReservationRequest request = new ReservationRequest("에버", LocalDate.of(2030, 1, 11), 1L, 1L); + ReservationDto request = new ReservationDto("에버", LocalDate.of(2030, 1, 11), 1L, 1L); assertThatCode(() -> reservationService.addReservation(request)) .doesNotThrowAnyException(); } @@ -93,7 +94,7 @@ void should_not_throw_exception_when_later_date() { @DisplayName("날짜, 시간이 일치하는 예약을 추가하려 할 때 예외가 발생한다.") @Test void should_throw_exception_when_add_exist_reservation() { - ReservationRequest request = new ReservationRequest("배키", LocalDate.of(2030, 8, 5), 2L, 2L); + ReservationDto request = new ReservationDto("배키", LocalDate.of(2030, 8, 5), 2L, 2L); assertThatThrownBy(() -> reservationService.addReservation(request)) .isInstanceOf(DuplicatedException.class) .hasMessage("[ERROR] 중복되는 예약은 추가할 수 없습니다."); diff --git a/src/test/java/roomescape/service/ReservationTimeServiceTest.java b/src/test/java/roomescape/service/ReservationTimeServiceTest.java index df7a28b7d1..85e258b802 100644 --- a/src/test/java/roomescape/service/ReservationTimeServiceTest.java +++ b/src/test/java/roomescape/service/ReservationTimeServiceTest.java @@ -2,11 +2,11 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import roomescape.controller.request.ReservationTimeRequest; import roomescape.exception.BadRequestException; import roomescape.exception.DuplicatedException; import roomescape.exception.NotFoundException; import roomescape.model.ReservationTime; +import roomescape.service.dto.ReservationTimeDto; import java.time.LocalTime; import java.util.List; @@ -37,8 +37,7 @@ void should_get_reservation_time() { @DisplayName("예약 시간을 추가한다") @Test void should_add_reservation_times() { - ReservationTime reservationTime - = reservationTimeService.addReservationTime(new ReservationTimeRequest(LocalTime.of(12, 0))); + reservationTimeService.addReservationTime(new ReservationTimeDto(LocalTime.of(12, 0))); List allReservationTimes = reservationTimeService.findAllReservationTimes(); assertThat(allReservationTimes).hasSize(3); } @@ -77,8 +76,7 @@ void should_throw_exception_when_exist_reservation_using_time() { @DisplayName("존재하는 시간을 추가하려 할 때 예외가 발생한다.") @Test void should_throw_exception_when_add_exist_time() { - ReservationTimeRequest request = new ReservationTimeRequest(LocalTime.of(10, 0)); - assertThatThrownBy(() -> reservationTimeService.addReservationTime(request)) + assertThatThrownBy(() -> reservationTimeService.addReservationTime(new ReservationTimeDto(LocalTime.of(10, 0)))) .isInstanceOf(DuplicatedException.class) .hasMessage("[ERROR] 중복되는 시간은 추가할 수 없습니다."); } diff --git a/src/test/java/roomescape/service/ThemeServiceTest.java b/src/test/java/roomescape/service/ThemeServiceTest.java index b19ea7e5af..f2ae30aea8 100644 --- a/src/test/java/roomescape/service/ThemeServiceTest.java +++ b/src/test/java/roomescape/service/ThemeServiceTest.java @@ -4,6 +4,7 @@ import org.junit.jupiter.api.Test; import roomescape.controller.request.ThemeRequest; import roomescape.model.Theme; +import roomescape.service.dto.ThemeDto; import java.util.List; @@ -22,8 +23,8 @@ void should_find_all_themes() { @DisplayName("테마를 저장한다.") @Test void should_add_theme() { - ThemeRequest themeRequest = new ThemeRequest("에버", "공포", "공포.jpg"); - themeService.addTheme(themeRequest); + ThemeDto themeDto = new ThemeDto("에버", "공포", "공포.jpg"); + themeService.addTheme(themeDto); assertThat(themeService.findAllThemes()).hasSize(4); } From 1cb21401e9d0dd533264219a5a26ab0927eb9f8f Mon Sep 17 00:00:00 2001 From: SCY Date: Fri, 3 May 2024 16:01:18 +0900 Subject: [PATCH 39/74] =?UTF-8?q?refactor(repository):=20=EC=BF=BC?= =?UTF-8?q?=EB=A6=AC=EC=97=90=20=EB=94=B0=EB=A5=B8=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=20=EB=84=A4=EC=9D=B4=EB=B0=8D=20=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/roomescape/repository/ReservationDAO.java | 8 ++++---- .../roomescape/repository/ReservationRepository.java | 9 +++++---- .../java/roomescape/repository/ReservationTimeDAO.java | 4 ++-- .../repository/ReservationTimeRepository.java | 5 +++-- src/main/java/roomescape/repository/ThemeDAO.java | 4 ++-- .../java/roomescape/repository/ThemeRepository.java | 4 ++-- .../java/roomescape/service/ReservationService.java | 8 ++++---- .../roomescape/service/ReservationTimeService.java | 4 ++-- src/main/java/roomescape/service/ThemeService.java | 4 ++-- .../java/roomescape/repository/ReservationDAOTest.java | 10 +++++----- .../roomescape/repository/ReservationTimeDAOTest.java | 4 ++-- src/test/java/roomescape/repository/ThemeDAOTest.java | 4 ++-- .../roomescape/service/FakeReservationRepository.java | 8 ++++---- .../service/FakeReservationTimeRepository.java | 4 ++-- .../java/roomescape/service/FakeThemeRepository.java | 4 ++-- 15 files changed, 43 insertions(+), 41 deletions(-) diff --git a/src/main/java/roomescape/repository/ReservationDAO.java b/src/main/java/roomescape/repository/ReservationDAO.java index b0d80782b9..c297cddb30 100644 --- a/src/main/java/roomescape/repository/ReservationDAO.java +++ b/src/main/java/roomescape/repository/ReservationDAO.java @@ -28,7 +28,7 @@ public ReservationDAO(JdbcTemplate jdbcTemplate, DataSource dataSource) { } @Override - public List getAllReservations() { + public List findAllReservations() { String sql = """ select r.id as reservation_id, @@ -63,7 +63,7 @@ public List getAllReservations() { } @Override - public Reservation addReservation(Reservation reservation) { + public Reservation saveReservation(Reservation reservation) { Map parameters = new HashMap<>(3); parameters.put("name", reservation.getName()); parameters.put("date", reservation.getDate()); @@ -74,7 +74,7 @@ public Reservation addReservation(Reservation reservation) { } @Override - public void deleteReservation(long id) { + public void deleteReservationById(long id) { String sql = "delete from reservation where id = ?"; jdbcTemplate.update(sql, id); } @@ -98,7 +98,7 @@ public Long countReservationByDateAndTimeId(LocalDate date, long timeId) { } @Override - public List findReservationTimeByDateAndTheme(LocalDate date, long themeId) { + public List findReservationTimeByDateAndThemeId(LocalDate date, long themeId) { String sql = """ select t.id as time_id, t.start_at as start_at from reservation as r inner join reservation_time as t on r.time_id = t.id diff --git a/src/main/java/roomescape/repository/ReservationRepository.java b/src/main/java/roomescape/repository/ReservationRepository.java index 47d29ac4e9..9d9c8eca81 100644 --- a/src/main/java/roomescape/repository/ReservationRepository.java +++ b/src/main/java/roomescape/repository/ReservationRepository.java @@ -7,11 +7,12 @@ import java.util.List; public interface ReservationRepository { - List getAllReservations(); - Reservation addReservation(Reservation reservation); + List findAllReservations(); - void deleteReservation(long id); + Reservation saveReservation(Reservation reservation); + + void deleteReservationById(long id); Long countReservationById(long id); @@ -19,5 +20,5 @@ public interface ReservationRepository { Long countReservationByDateAndTimeId(LocalDate date, long timeId); - List findReservationTimeByDateAndTheme(LocalDate date, long themeId); + List findReservationTimeByDateAndThemeId(LocalDate date, long themeId); } diff --git a/src/main/java/roomescape/repository/ReservationTimeDAO.java b/src/main/java/roomescape/repository/ReservationTimeDAO.java index 204f64c8e9..c8a976b7db 100644 --- a/src/main/java/roomescape/repository/ReservationTimeDAO.java +++ b/src/main/java/roomescape/repository/ReservationTimeDAO.java @@ -46,7 +46,7 @@ public ReservationTime findReservationById(long id) { } @Override - public ReservationTime addReservationTime(ReservationTime reservationTime) { + public ReservationTime saveReservationTime(ReservationTime reservationTime) { Map parameters = new HashMap<>(1); parameters.put("start_at", reservationTime.getStartAt()); Number newId = insertActor.executeAndReturnKey(parameters); @@ -54,7 +54,7 @@ public ReservationTime addReservationTime(ReservationTime reservationTime) { } @Override - public void deleteReservationTime(long id) { + public void deleteReservationTimeById(long id) { String sql = "delete from reservation_time where id = ?"; jdbcTemplate.update(sql, id); } diff --git a/src/main/java/roomescape/repository/ReservationTimeRepository.java b/src/main/java/roomescape/repository/ReservationTimeRepository.java index 5548fd5665..a407c0af4c 100644 --- a/src/main/java/roomescape/repository/ReservationTimeRepository.java +++ b/src/main/java/roomescape/repository/ReservationTimeRepository.java @@ -6,13 +6,14 @@ import java.util.List; public interface ReservationTimeRepository { + List findAllReservationTimes(); ReservationTime findReservationById(long id); - ReservationTime addReservationTime(ReservationTime reservationTime); + ReservationTime saveReservationTime(ReservationTime reservationTime); - void deleteReservationTime(long id); + void deleteReservationTimeById(long id); Long countReservationTimeById(long id); diff --git a/src/main/java/roomescape/repository/ThemeDAO.java b/src/main/java/roomescape/repository/ThemeDAO.java index 809f3051a3..81d43e6723 100644 --- a/src/main/java/roomescape/repository/ThemeDAO.java +++ b/src/main/java/roomescape/repository/ThemeDAO.java @@ -37,7 +37,7 @@ public List findAllThemes() { } @Override - public Theme addTheme(Theme theme) { + public Theme saveTheme(Theme theme) { Map parameters = new HashMap<>(1); parameters.put("name", theme.getName()); parameters.put("description", theme.getDescription()); @@ -47,7 +47,7 @@ public Theme addTheme(Theme theme) { } @Override - public void deleteTheme(long id) { + public void deleteThemeById(long id) { String sql = "delete from theme where id = ?"; jdbcTemplate.update(sql, id); } diff --git a/src/main/java/roomescape/repository/ThemeRepository.java b/src/main/java/roomescape/repository/ThemeRepository.java index 7d1eb65106..a812e51fff 100644 --- a/src/main/java/roomescape/repository/ThemeRepository.java +++ b/src/main/java/roomescape/repository/ThemeRepository.java @@ -9,9 +9,9 @@ public interface ThemeRepository { List findAllThemes(); - Theme addTheme(Theme theme); + Theme saveTheme(Theme theme); - void deleteTheme(long id); + void deleteThemeById(long id); Theme findThemeById(long id); diff --git a/src/main/java/roomescape/service/ReservationService.java b/src/main/java/roomescape/service/ReservationService.java index 58c94fe0de..eaf8b844df 100644 --- a/src/main/java/roomescape/service/ReservationService.java +++ b/src/main/java/roomescape/service/ReservationService.java @@ -35,7 +35,7 @@ public ReservationService(ReservationRepository reservationRepository, } public List findAllReservations() { - return reservationRepository.getAllReservations(); + return reservationRepository.findAllReservations(); } public Reservation addReservation(ReservationDto reservationDto) { @@ -54,7 +54,7 @@ public Reservation addReservation(ReservationDto reservationDto) { throw new DuplicatedException("[ERROR] 중복되는 예약은 추가할 수 없습니다."); } Reservation reservation = new Reservation(reservationDto.getName(), reservationDto.getDate(), reservationTime, theme); - return reservationRepository.addReservation(reservation); + return reservationRepository.saveReservation(reservation); } public void deleteReservation(long id) { @@ -62,12 +62,12 @@ public void deleteReservation(long id) { if (count == null || count <= 0) { throw new NotFoundException("[ERROR] 존재하지 않는 예약입니다."); } - reservationRepository.deleteReservation(id); + reservationRepository.deleteReservationById(id); } public List getMemberReservationTimes(LocalDate date, long themeId) { List allTimes = reservationTimeRepository.findAllReservationTimes(); - List bookedTimes = reservationRepository.findReservationTimeByDateAndTheme(date, themeId); + List bookedTimes = reservationRepository.findReservationTimeByDateAndThemeId(date, themeId); List notBookedTimes = filterNotBookedTimes(allTimes, bookedTimes); List bookedResponse = mapToResponse(bookedTimes, true); List notBookedResponse = mapToResponse(notBookedTimes, false); diff --git a/src/main/java/roomescape/service/ReservationTimeService.java b/src/main/java/roomescape/service/ReservationTimeService.java index 4c9709d685..d2b0a08e71 100644 --- a/src/main/java/roomescape/service/ReservationTimeService.java +++ b/src/main/java/roomescape/service/ReservationTimeService.java @@ -34,7 +34,7 @@ public ReservationTime addReservationTime(ReservationTimeDto reservationTimeDto) throw new DuplicatedException("[ERROR] 중복되는 시간은 추가할 수 없습니다."); } ReservationTime reservationTime = new ReservationTime(reservationTimeDto.getStartAt()); - return reservationTimeRepository.addReservationTime(reservationTime); + return reservationTimeRepository.saveReservationTime(reservationTime); } public ReservationTime findReservationTime(long id) { @@ -50,6 +50,6 @@ public void deleteReservationTime(long id) { if (countOfReservationUsingTime == null || countOfReservationUsingTime > 0) { throw new BadRequestException("[ERROR] 해당 시간을 사용하고 있는 예약이 있습니다."); } - reservationTimeRepository.deleteReservationTime(id); + reservationTimeRepository.deleteReservationTimeById(id); } } diff --git a/src/main/java/roomescape/service/ThemeService.java b/src/main/java/roomescape/service/ThemeService.java index 6561e183fb..5fd7043cf6 100644 --- a/src/main/java/roomescape/service/ThemeService.java +++ b/src/main/java/roomescape/service/ThemeService.java @@ -23,11 +23,11 @@ public List findAllThemes() { public Theme addTheme(ThemeDto themeDto) { Theme theme = Theme.from(themeDto); - return themeRepository.addTheme(theme); + return themeRepository.saveTheme(theme); } public void deleteTheme(long id) { - themeRepository.deleteTheme(id); + themeRepository.deleteThemeById(id); } public List findPopularThemes() { diff --git a/src/test/java/roomescape/repository/ReservationDAOTest.java b/src/test/java/roomescape/repository/ReservationDAOTest.java index 360b923e4d..24f34efe3e 100644 --- a/src/test/java/roomescape/repository/ReservationDAOTest.java +++ b/src/test/java/roomescape/repository/ReservationDAOTest.java @@ -91,14 +91,14 @@ private void insertTheme(String name, String description, String thumbnail) { @DisplayName("모든 예약을 조회한다") @Test void should_get_reservation() { - List reservations = reservationRepository.getAllReservations(); + List reservations = reservationRepository.findAllReservations(); assertThat(reservations).hasSize(2); } @DisplayName("조회한 예약에 예약 시간이 존재한다.") @Test void should_get_reservation_times() { - List reservations = reservationRepository.getAllReservations(); + List reservations = reservationRepository.findAllReservations(); assertThat(reservations.get(0).getTime().getStartAt()).isEqualTo(LocalTime.of(10, 0)); } @@ -109,7 +109,7 @@ void should_add_reservation() { Theme theme = new Theme(1, "에버", "공포", "공포.jpg"); Reservation reservation = new Reservation("네오", LocalDate.of(2024, 9, 1), reservationTime, theme); - reservationRepository.addReservation(reservation); + reservationRepository.saveReservation(reservation); Integer count = jdbcTemplate.queryForObject("select count(1) from reservation", Integer.class); assertThat(count).isEqualTo(3); @@ -118,7 +118,7 @@ void should_add_reservation() { @DisplayName("예약을 삭제한다") @Test void should_delete_reservation() { - reservationRepository.deleteReservation(1); + reservationRepository.deleteReservationById(1); Integer count = jdbcTemplate.queryForObject("select count(1) from reservation", Integer.class); assertThat(count).isEqualTo(1); } @@ -141,7 +141,7 @@ void should_return_false_when_id_not_exist() { @Test void should_get_reservation_times_when_date_and_theme_given() { LocalDate date = LocalDate.of(2023, 8, 5); - List times = reservationRepository.findReservationTimeByDateAndTheme(date, 1); + List times = reservationRepository.findReservationTimeByDateAndThemeId(date, 1); assertThat(times).hasSize(1); assertThat(times).containsExactly(new ReservationTime(1, LocalTime.of(10, 0))); } diff --git a/src/test/java/roomescape/repository/ReservationTimeDAOTest.java b/src/test/java/roomescape/repository/ReservationTimeDAOTest.java index 53ba07235c..13a08165a4 100644 --- a/src/test/java/roomescape/repository/ReservationTimeDAOTest.java +++ b/src/test/java/roomescape/repository/ReservationTimeDAOTest.java @@ -62,7 +62,7 @@ void should_get_reservation_times() { @DisplayName("예약 시간을 추가한다") @Test void should_add_reservation_time() { - reservationTimeRepository.addReservationTime(new ReservationTime(LocalTime.of(12, 0))); + reservationTimeRepository.saveReservationTime(new ReservationTime(LocalTime.of(12, 0))); Integer count = jdbcTemplate.queryForObject("select count(1) from reservation_time", Integer.class); assertThat(count).isEqualTo(3); } @@ -70,7 +70,7 @@ void should_add_reservation_time() { @DisplayName("예약 시간을 삭제한다") @Test void should_delete_reservation_time() { - reservationTimeRepository.deleteReservationTime(1); + reservationTimeRepository.deleteReservationTimeById(1); Integer count = jdbcTemplate.queryForObject("select count(1) from reservation_time", Integer.class); assertThat(count).isEqualTo(1); } diff --git a/src/test/java/roomescape/repository/ThemeDAOTest.java b/src/test/java/roomescape/repository/ThemeDAOTest.java index e76c546390..6f4ef2c18b 100644 --- a/src/test/java/roomescape/repository/ThemeDAOTest.java +++ b/src/test/java/roomescape/repository/ThemeDAOTest.java @@ -73,14 +73,14 @@ void should_find_all_themes() { @Test void should_add_theme() { Theme theme = new Theme("브라운", "공포", "공포.jpg"); - themeRepository.addTheme(theme); + themeRepository.saveTheme(theme); assertThat(themeRepository.findAllThemes()).hasSize(3); } @DisplayName("테마를 삭제한다.") @Test void should_delete_theme() { - themeRepository.deleteTheme(1); + themeRepository.deleteThemeById(1); assertThat(themeRepository.findAllThemes()).hasSize(1); } diff --git a/src/test/java/roomescape/service/FakeReservationRepository.java b/src/test/java/roomescape/service/FakeReservationRepository.java index ea0a31ced9..eb9a309bca 100644 --- a/src/test/java/roomescape/service/FakeReservationRepository.java +++ b/src/test/java/roomescape/service/FakeReservationRepository.java @@ -22,18 +22,18 @@ class FakeReservationRepository implements ReservationRepository { new Theme(2, "배키", "스릴러", "스릴러.jpg")))); @Override - public List getAllReservations() { + public List findAllReservations() { return reservations; } @Override - public Reservation addReservation(Reservation reservation) { + public Reservation saveReservation(Reservation reservation) { reservations.add(reservation); return reservation; } @Override - public void deleteReservation(long id) { + public void deleteReservationById(long id) { Reservation foundReservation = reservations.stream() .filter(reservation -> reservation.getId() == id) .findFirst() @@ -64,7 +64,7 @@ public Long countReservationByDateAndTimeId(LocalDate date, long timeId) { } @Override - public List findReservationTimeByDateAndTheme(LocalDate date, long themeId) { + public List findReservationTimeByDateAndThemeId(LocalDate date, long themeId) { return reservations.stream() .filter(reservation -> reservation.getDate().equals(date) && reservation.getTheme().getThemeId() == themeId) .map(reservation -> new ReservationTime(reservation.getTime().getId(), reservation.getTime().getStartAt())) diff --git a/src/test/java/roomescape/service/FakeReservationTimeRepository.java b/src/test/java/roomescape/service/FakeReservationTimeRepository.java index 97cb3f8bd8..87f724d08e 100644 --- a/src/test/java/roomescape/service/FakeReservationTimeRepository.java +++ b/src/test/java/roomescape/service/FakeReservationTimeRepository.java @@ -33,13 +33,13 @@ public ReservationTime findReservationById(long id) { } @Override - public ReservationTime addReservationTime(ReservationTime reservationTime) { + public ReservationTime saveReservationTime(ReservationTime reservationTime) { reservationTimes.add(reservationTime); return new ReservationTime(3, reservationTime.getStartAt()); } @Override - public void deleteReservationTime(long id) { + public void deleteReservationTimeById(long id) { ReservationTime findReservationTime = reservationTimes.stream() .filter(reservationTime -> reservationTime.getId() == id) .findFirst() diff --git a/src/test/java/roomescape/service/FakeThemeRepository.java b/src/test/java/roomescape/service/FakeThemeRepository.java index e6efe5a3c9..87f2f13558 100644 --- a/src/test/java/roomescape/service/FakeThemeRepository.java +++ b/src/test/java/roomescape/service/FakeThemeRepository.java @@ -25,14 +25,14 @@ public List findAllThemes() { } @Override - public Theme addTheme(Theme theme) { + public Theme saveTheme(Theme theme) { Theme newTheme = new Theme(index.getAndIncrement(), theme.getName(), theme.getDescription(), theme.getThumbnail()); themes.add(newTheme); return newTheme; } @Override - public void deleteTheme(long id) { + public void deleteThemeById(long id) { Theme targetTheme = themes.stream() .filter(theme -> theme.getThemeId() == id) .findFirst() From 8c4c09bced7c15b18aca6a37a76f2c85ebdd19ea Mon Sep 17 00:00:00 2001 From: SCY Date: Fri, 3 May 2024 16:05:37 +0900 Subject: [PATCH 40/74] =?UTF-8?q?refactor(all):=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=EB=AA=85=20=ED=98=95=EC=8B=9D=20=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/ReservationController.java | 10 +++++----- .../controller/ReservationTimeController.java | 6 +++--- .../java/roomescape/controller/ThemeController.java | 6 +++--- .../java/roomescape/service/ReservationService.java | 4 ++-- .../roomescape/service/ReservationTimeService.java | 2 +- src/main/java/roomescape/service/ThemeService.java | 2 +- .../roomescape/service/ReservationServiceTest.java | 13 ++++++------- .../service/ReservationTimeServiceTest.java | 4 ++-- .../java/roomescape/service/ThemeServiceTest.java | 3 +-- 9 files changed, 24 insertions(+), 26 deletions(-) diff --git a/src/main/java/roomescape/controller/ReservationController.java b/src/main/java/roomescape/controller/ReservationController.java index dba82c2d59..7c3ef5613c 100644 --- a/src/main/java/roomescape/controller/ReservationController.java +++ b/src/main/java/roomescape/controller/ReservationController.java @@ -24,7 +24,7 @@ public ReservationController(ReservationService reservationService) { } @GetMapping - public ResponseEntity> getReservations() { + public ResponseEntity> showReservations() { List reservations = reservationService.findAllReservations(); List response = reservations.stream() .map(ReservationResponse::from) @@ -33,9 +33,9 @@ public ResponseEntity> getReservations() { } @PostMapping - public ResponseEntity createReservation(@RequestBody ReservationRequest request) { + public ResponseEntity addReservation(@RequestBody ReservationRequest request) { ReservationDto reservationDto = ReservationDto.from(request); - Reservation reservation = reservationService.addReservation(reservationDto); + Reservation reservation = reservationService.saveReservation(reservationDto); ReservationResponse response = ReservationResponse.from(reservation); return ResponseEntity .created(URI.create("/reservations/" + response.getId())) @@ -49,10 +49,10 @@ public ResponseEntity deleteReservation(@PathVariable("id") long id) { } @GetMapping("/times") - public ResponseEntity> getPossibleReservationTimes( + public ResponseEntity> showReservationTimesInformation( @RequestParam(name = "date") LocalDate date, @RequestParam(name = "themeId") long themeId) { - List response = reservationService.getMemberReservationTimes(date, themeId); + List response = reservationService.findReservationTimesInformation(date, themeId); // TODO: 여기서 response 객체로 반환하도록 수정 return ResponseEntity.ok(response); } diff --git a/src/main/java/roomescape/controller/ReservationTimeController.java b/src/main/java/roomescape/controller/ReservationTimeController.java index 079174d0d6..d0f2dfc6dc 100644 --- a/src/main/java/roomescape/controller/ReservationTimeController.java +++ b/src/main/java/roomescape/controller/ReservationTimeController.java @@ -22,7 +22,7 @@ public ReservationTimeController(ReservationTimeService reservationTimeService) } @GetMapping - public ResponseEntity> getReservationTimes() { + public ResponseEntity> showReservationTimes() { List times = reservationTimeService.findAllReservationTimes(); List response = times.stream() .map(ReservationTimeResponse::from) @@ -31,9 +31,9 @@ public ResponseEntity> getReservationTimes() { } @PostMapping - public ResponseEntity createReservationTime(@RequestBody ReservationTimeRequest request) { + public ResponseEntity addReservationTime(@RequestBody ReservationTimeRequest request) { ReservationTimeDto timeDto = ReservationTimeDto.from(request); - ReservationTime time = reservationTimeService.addReservationTime(timeDto); + ReservationTime time = reservationTimeService.saveReservationTime(timeDto); ReservationTimeResponse response = ReservationTimeResponse.from(time); return ResponseEntity .created(URI.create("/times/" + response.getId())) diff --git a/src/main/java/roomescape/controller/ThemeController.java b/src/main/java/roomescape/controller/ThemeController.java index d97f6e42b4..0f2639f17d 100644 --- a/src/main/java/roomescape/controller/ThemeController.java +++ b/src/main/java/roomescape/controller/ThemeController.java @@ -22,7 +22,7 @@ public ThemeController(ThemeService themeService) { } @GetMapping - public ResponseEntity> getThemes() { + public ResponseEntity> showThemes() { List themes = themeService.findAllThemes(); List response = themes.stream() .map(ThemeResponse::from) @@ -33,7 +33,7 @@ public ResponseEntity> getThemes() { @PostMapping public ResponseEntity addTheme(@RequestBody ThemeRequest request) { ThemeDto themeDto = ThemeDto.from(request); - Theme theme = themeService.addTheme(themeDto); + Theme theme = themeService.saveTheme(themeDto); ThemeResponse response = ThemeResponse.from(theme); return ResponseEntity .created(URI.create("/themes/" + response.getId())) @@ -47,7 +47,7 @@ public ResponseEntity deleteTheme(@PathVariable(name = "id") long id) { } @GetMapping("/rank") - public ResponseEntity> getPopularThemes() { + public ResponseEntity> showPopularThemes() { List themes = themeService.findPopularThemes(); List response = themes.stream() .map(ThemeResponse::from) diff --git a/src/main/java/roomescape/service/ReservationService.java b/src/main/java/roomescape/service/ReservationService.java index eaf8b844df..682e8b26b0 100644 --- a/src/main/java/roomescape/service/ReservationService.java +++ b/src/main/java/roomescape/service/ReservationService.java @@ -38,7 +38,7 @@ public List findAllReservations() { return reservationRepository.findAllReservations(); } - public Reservation addReservation(ReservationDto reservationDto) { + public Reservation saveReservation(ReservationDto reservationDto) { ReservationTime reservationTime = reservationTimeRepository.findReservationById(reservationDto.getTimeId()); Theme theme = themeRepository.findThemeById(reservationDto.getThemeId()); @@ -65,7 +65,7 @@ public void deleteReservation(long id) { reservationRepository.deleteReservationById(id); } - public List getMemberReservationTimes(LocalDate date, long themeId) { + public List findReservationTimesInformation(LocalDate date, long themeId) { List allTimes = reservationTimeRepository.findAllReservationTimes(); List bookedTimes = reservationRepository.findReservationTimeByDateAndThemeId(date, themeId); List notBookedTimes = filterNotBookedTimes(allTimes, bookedTimes); diff --git a/src/main/java/roomescape/service/ReservationTimeService.java b/src/main/java/roomescape/service/ReservationTimeService.java index d2b0a08e71..0a9f74f359 100644 --- a/src/main/java/roomescape/service/ReservationTimeService.java +++ b/src/main/java/roomescape/service/ReservationTimeService.java @@ -27,7 +27,7 @@ public List findAllReservationTimes() { return reservationTimeRepository.findAllReservationTimes(); } - public ReservationTime addReservationTime(ReservationTimeDto reservationTimeDto) { + public ReservationTime saveReservationTime(ReservationTimeDto reservationTimeDto) { LocalTime startAt = reservationTimeDto.getStartAt(); Long countReservationTimeByStartAt = reservationTimeRepository.countReservationTimeByStartAt(startAt); if (countReservationTimeByStartAt == null || countReservationTimeByStartAt > 0) { diff --git a/src/main/java/roomescape/service/ThemeService.java b/src/main/java/roomescape/service/ThemeService.java index 5fd7043cf6..27a8228059 100644 --- a/src/main/java/roomescape/service/ThemeService.java +++ b/src/main/java/roomescape/service/ThemeService.java @@ -21,7 +21,7 @@ public List findAllThemes() { return themeRepository.findAllThemes(); } - public Theme addTheme(ThemeDto themeDto) { + public Theme saveTheme(ThemeDto themeDto) { Theme theme = Theme.from(themeDto); return themeRepository.saveTheme(theme); } diff --git a/src/test/java/roomescape/service/ReservationServiceTest.java b/src/test/java/roomescape/service/ReservationServiceTest.java index e1562c6e11..eaf92370bd 100644 --- a/src/test/java/roomescape/service/ReservationServiceTest.java +++ b/src/test/java/roomescape/service/ReservationServiceTest.java @@ -2,7 +2,6 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import roomescape.controller.request.ReservationRequest; import roomescape.controller.response.MemberReservationTimeResponse; import roomescape.exception.BadRequestException; import roomescape.exception.DuplicatedException; @@ -36,7 +35,7 @@ void should_return_all_reservation_times() { @DisplayName("예약 시간을 추가한다") @Test void should_add_reservation_times() { - reservationService.addReservation( + reservationService.saveReservation( new ReservationDto("네오", LocalDate.of(2030, 1, 1), 1L, 1L)); List allReservations = reservationService.findAllReservations(); assertThat(allReservations).hasSize(3); @@ -69,7 +68,7 @@ void should_not_throw_exception_when_exist_reservation_time() { @Test void should_throw_exception_when_previous_date() { ReservationDto request = new ReservationDto("에버", LocalDate.of(2000, 1, 11), 1L, 1L); - assertThatThrownBy(() -> reservationService.addReservation(request)) + assertThatThrownBy(() -> reservationService.saveReservation(request)) .isInstanceOf(BadRequestException.class) .hasMessage("[ERROR] 현재 이전 예약은 할 수 없습니다."); } @@ -79,7 +78,7 @@ void should_throw_exception_when_previous_date() { void should_not_throw_exception_when_current_date() { reservationTimeRepository.add(new ReservationTime(3, LocalTime.now())); ReservationDto request = new ReservationDto("에버", LocalDate.now(), 3L, 1L); - assertThatCode(() -> reservationService.addReservation(request)) + assertThatCode(() -> reservationService.saveReservation(request)) .doesNotThrowAnyException(); } @@ -87,7 +86,7 @@ void should_not_throw_exception_when_current_date() { @Test void should_not_throw_exception_when_later_date() { ReservationDto request = new ReservationDto("에버", LocalDate.of(2030, 1, 11), 1L, 1L); - assertThatCode(() -> reservationService.addReservation(request)) + assertThatCode(() -> reservationService.saveReservation(request)) .doesNotThrowAnyException(); } @@ -95,7 +94,7 @@ void should_not_throw_exception_when_later_date() { @Test void should_throw_exception_when_add_exist_reservation() { ReservationDto request = new ReservationDto("배키", LocalDate.of(2030, 8, 5), 2L, 2L); - assertThatThrownBy(() -> reservationService.addReservation(request)) + assertThatThrownBy(() -> reservationService.saveReservation(request)) .isInstanceOf(DuplicatedException.class) .hasMessage("[ERROR] 중복되는 예약은 추가할 수 없습니다."); } @@ -103,7 +102,7 @@ void should_throw_exception_when_add_exist_reservation() { @DisplayName("예약 가능 상태를 담은 시간 정보를 반환한다.") @Test void should_return_times_with_book_state() { - List times = reservationService.getMemberReservationTimes(LocalDate.of(2030, 8, 5), 1); + List times = reservationService.findReservationTimesInformation(LocalDate.of(2030, 8, 5), 1); assertThat(times).hasSize(2); assertThat(times).containsOnly( new MemberReservationTimeResponse(1, LocalTime.of(10, 0), false), diff --git a/src/test/java/roomescape/service/ReservationTimeServiceTest.java b/src/test/java/roomescape/service/ReservationTimeServiceTest.java index 85e258b802..5f2e9cf63a 100644 --- a/src/test/java/roomescape/service/ReservationTimeServiceTest.java +++ b/src/test/java/roomescape/service/ReservationTimeServiceTest.java @@ -37,7 +37,7 @@ void should_get_reservation_time() { @DisplayName("예약 시간을 추가한다") @Test void should_add_reservation_times() { - reservationTimeService.addReservationTime(new ReservationTimeDto(LocalTime.of(12, 0))); + reservationTimeService.saveReservationTime(new ReservationTimeDto(LocalTime.of(12, 0))); List allReservationTimes = reservationTimeService.findAllReservationTimes(); assertThat(allReservationTimes).hasSize(3); } @@ -76,7 +76,7 @@ void should_throw_exception_when_exist_reservation_using_time() { @DisplayName("존재하는 시간을 추가하려 할 때 예외가 발생한다.") @Test void should_throw_exception_when_add_exist_time() { - assertThatThrownBy(() -> reservationTimeService.addReservationTime(new ReservationTimeDto(LocalTime.of(10, 0)))) + assertThatThrownBy(() -> reservationTimeService.saveReservationTime(new ReservationTimeDto(LocalTime.of(10, 0)))) .isInstanceOf(DuplicatedException.class) .hasMessage("[ERROR] 중복되는 시간은 추가할 수 없습니다."); } diff --git a/src/test/java/roomescape/service/ThemeServiceTest.java b/src/test/java/roomescape/service/ThemeServiceTest.java index f2ae30aea8..af06633619 100644 --- a/src/test/java/roomescape/service/ThemeServiceTest.java +++ b/src/test/java/roomescape/service/ThemeServiceTest.java @@ -2,7 +2,6 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import roomescape.controller.request.ThemeRequest; import roomescape.model.Theme; import roomescape.service.dto.ThemeDto; @@ -24,7 +23,7 @@ void should_find_all_themes() { @Test void should_add_theme() { ThemeDto themeDto = new ThemeDto("에버", "공포", "공포.jpg"); - themeService.addTheme(themeDto); + themeService.saveTheme(themeDto); assertThat(themeService.findAllThemes()).hasSize(4); } From 1ac4a1b05d9fd4467de9d574f17678081e0b1fc1 Mon Sep 17 00:00:00 2001 From: SCY Date: Fri, 3 May 2024 16:41:05 +0900 Subject: [PATCH 41/74] =?UTF-8?q?refactor(all):=20repository=EC=99=80=20da?= =?UTF-8?q?o=20=EA=B3=84=EC=B8=B5=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...vationDAO.java => JdbcReservationDao.java} | 4 +- ...meDAO.java => JdbcReservationTimeDao.java} | 6 +-- .../{ThemeDAO.java => JdbcThemeDao.java} | 4 +- .../roomescape/repository/ReservationDao.java | 24 +++++++++ .../repository/ReservationRepository.java | 51 ++++++++++++++++--- .../repository/ReservationTimeDao.java | 21 ++++++++ .../repository/ReservationTimeRepository.java | 40 ++++++++++++--- .../java/roomescape/repository/ThemeDao.java | 19 +++++++ .../repository/ThemeRepository.java | 26 +++++++--- .../service/ReservationService.java | 16 ++---- .../service/ReservationTimeService.java | 7 +-- .../controller/ReservationControllerTest.java | 1 - .../controller/ThemeControllerTest.java | 4 +- .../repository/ReservationDAOTest.java | 16 +++--- .../repository/ReservationTimeDAOTest.java | 14 ++--- .../roomescape/repository/ThemeDAOTest.java | 14 ++--- ...epository.java => FakeReservationDao.java} | 4 +- ...itory.java => FakeReservationTimeDao.java} | 6 +-- ...ThemeRepository.java => FakeThemeDao.java} | 4 +- .../service/ReservationServiceTest.java | 15 +++--- .../service/ReservationTimeServiceTest.java | 9 ++-- .../roomescape/service/ThemeServiceTest.java | 4 +- 22 files changed, 220 insertions(+), 89 deletions(-) rename src/main/java/roomescape/repository/{ReservationDAO.java => JdbcReservationDao.java} (96%) rename src/main/java/roomescape/repository/{ReservationTimeDAO.java => JdbcReservationTimeDao.java} (92%) rename src/main/java/roomescape/repository/{ThemeDAO.java => JdbcThemeDao.java} (96%) create mode 100644 src/main/java/roomescape/repository/ReservationDao.java create mode 100644 src/main/java/roomescape/repository/ReservationTimeDao.java create mode 100644 src/main/java/roomescape/repository/ThemeDao.java rename src/test/java/roomescape/service/{FakeReservationRepository.java => FakeReservationDao.java} (95%) rename src/test/java/roomescape/service/{FakeReservationTimeRepository.java => FakeReservationTimeDao.java} (91%) rename src/test/java/roomescape/service/{FakeThemeRepository.java => FakeThemeDao.java} (95%) diff --git a/src/main/java/roomescape/repository/ReservationDAO.java b/src/main/java/roomescape/repository/JdbcReservationDao.java similarity index 96% rename from src/main/java/roomescape/repository/ReservationDAO.java rename to src/main/java/roomescape/repository/JdbcReservationDao.java index c297cddb30..3bbc7ad0b4 100644 --- a/src/main/java/roomescape/repository/ReservationDAO.java +++ b/src/main/java/roomescape/repository/JdbcReservationDao.java @@ -14,13 +14,13 @@ import java.util.Map; @Repository -public class ReservationDAO implements ReservationRepository { +public class JdbcReservationDao implements ReservationDao { private final JdbcTemplate jdbcTemplate; private SimpleJdbcInsert insertActor; - public ReservationDAO(JdbcTemplate jdbcTemplate, DataSource dataSource) { + public JdbcReservationDao(JdbcTemplate jdbcTemplate, DataSource dataSource) { this.jdbcTemplate = jdbcTemplate; this.insertActor = new SimpleJdbcInsert(dataSource) .withTableName("reservation") diff --git a/src/main/java/roomescape/repository/ReservationTimeDAO.java b/src/main/java/roomescape/repository/JdbcReservationTimeDao.java similarity index 92% rename from src/main/java/roomescape/repository/ReservationTimeDAO.java rename to src/main/java/roomescape/repository/JdbcReservationTimeDao.java index c8a976b7db..cbbdaf486d 100644 --- a/src/main/java/roomescape/repository/ReservationTimeDAO.java +++ b/src/main/java/roomescape/repository/JdbcReservationTimeDao.java @@ -12,13 +12,13 @@ import java.util.Map; @Repository -public class ReservationTimeDAO implements ReservationTimeRepository { +public class JdbcReservationTimeDao implements ReservationTimeDao { private final JdbcTemplate jdbcTemplate; private SimpleJdbcInsert insertActor; - public ReservationTimeDAO(JdbcTemplate jdbcTemplate, DataSource dataSource) { + public JdbcReservationTimeDao(JdbcTemplate jdbcTemplate, DataSource dataSource) { this.jdbcTemplate = jdbcTemplate; this.insertActor = new SimpleJdbcInsert(dataSource) .withTableName("reservation_time") @@ -36,7 +36,7 @@ public List findAllReservationTimes() { } @Override - public ReservationTime findReservationById(long id) { + public ReservationTime findReservationTimeById(long id) { String sql = "select * from reservation_time where id = ?"; return jdbcTemplate.queryForObject(sql, (resultSet, rowNum) -> new ReservationTime( diff --git a/src/main/java/roomescape/repository/ThemeDAO.java b/src/main/java/roomescape/repository/JdbcThemeDao.java similarity index 96% rename from src/main/java/roomescape/repository/ThemeDAO.java rename to src/main/java/roomescape/repository/JdbcThemeDao.java index 81d43e6723..a9c7988bbd 100644 --- a/src/main/java/roomescape/repository/ThemeDAO.java +++ b/src/main/java/roomescape/repository/JdbcThemeDao.java @@ -12,12 +12,12 @@ import java.util.Map; @Repository -public class ThemeDAO implements ThemeRepository { +public class JdbcThemeDao implements ThemeDao { private final JdbcTemplate jdbcTemplate; private SimpleJdbcInsert insertActor; - public ThemeDAO(JdbcTemplate jdbcTemplate, DataSource dataSource) { + public JdbcThemeDao(JdbcTemplate jdbcTemplate, DataSource dataSource) { this.jdbcTemplate = jdbcTemplate; this.insertActor = new SimpleJdbcInsert(dataSource) .withTableName("theme") diff --git a/src/main/java/roomescape/repository/ReservationDao.java b/src/main/java/roomescape/repository/ReservationDao.java new file mode 100644 index 0000000000..dae8ccac4a --- /dev/null +++ b/src/main/java/roomescape/repository/ReservationDao.java @@ -0,0 +1,24 @@ +package roomescape.repository; + +import roomescape.model.Reservation; +import roomescape.model.ReservationTime; + +import java.time.LocalDate; +import java.util.List; + +public interface ReservationDao { + + List findAllReservations(); + + Reservation saveReservation(Reservation reservation); + + void deleteReservationById(long id); + + Long countReservationById(long id); + + Long countReservationByTimeId(long timeId); + + Long countReservationByDateAndTimeId(LocalDate date, long timeId); + + List findReservationTimeByDateAndThemeId(LocalDate date, long themeId); +} diff --git a/src/main/java/roomescape/repository/ReservationRepository.java b/src/main/java/roomescape/repository/ReservationRepository.java index 9d9c8eca81..c8d387f9a6 100644 --- a/src/main/java/roomescape/repository/ReservationRepository.java +++ b/src/main/java/roomescape/repository/ReservationRepository.java @@ -1,24 +1,59 @@ package roomescape.repository; +import org.springframework.stereotype.Repository; import roomescape.model.Reservation; import roomescape.model.ReservationTime; +import roomescape.model.Theme; import java.time.LocalDate; import java.util.List; -public interface ReservationRepository { +@Repository +public class ReservationRepository { - List findAllReservations(); + private final ReservationDao reservationDao; + private final ReservationTimeDao reservationTimeDao; + private final ThemeDao themeDao; - Reservation saveReservation(Reservation reservation); + public ReservationRepository(ReservationDao reservationDao, ReservationTimeDao reservationTimeDao, ThemeDao themeDao) { + this.reservationDao = reservationDao; + this.reservationTimeDao = reservationTimeDao; + this.themeDao = themeDao; + } - void deleteReservationById(long id); + public List findAllReservations() { + return reservationDao.findAllReservations(); + } - Long countReservationById(long id); + public ReservationTime findReservationTimeById(long id) { + return reservationTimeDao.findReservationTimeById(id); + } - Long countReservationByTimeId(long timeId); + public Theme findThemeById(long id) { + return themeDao.findThemeById(id); + } - Long countReservationByDateAndTimeId(LocalDate date, long timeId); + public Long countReservationByDateAndTimeId(LocalDate date, long timeId) { + return reservationDao.countReservationByDateAndTimeId(date, timeId); + } - List findReservationTimeByDateAndThemeId(LocalDate date, long themeId); + public Reservation saveReservation(Reservation reservation) { + return reservationDao.saveReservation(reservation); + } + + public Long countReservationById(long id) { + return reservationDao.countReservationById(id); + } + + public void deleteReservationById(long id) { + reservationDao.deleteReservationById(id); + } + + public List findAllReservationTimes() { + return reservationTimeDao.findAllReservationTimes(); + } + + public List findReservationTimeByDateAndThemeId(LocalDate date, long themeId) { + return reservationDao.findReservationTimeByDateAndThemeId(date, themeId); + } } diff --git a/src/main/java/roomescape/repository/ReservationTimeDao.java b/src/main/java/roomescape/repository/ReservationTimeDao.java new file mode 100644 index 0000000000..59015d3fe4 --- /dev/null +++ b/src/main/java/roomescape/repository/ReservationTimeDao.java @@ -0,0 +1,21 @@ +package roomescape.repository; + +import roomescape.model.ReservationTime; + +import java.time.LocalTime; +import java.util.List; + +public interface ReservationTimeDao { + + List findAllReservationTimes(); + + ReservationTime findReservationTimeById(long id); + + ReservationTime saveReservationTime(ReservationTime reservationTime); + + void deleteReservationTimeById(long id); + + Long countReservationTimeById(long id); + + Long countReservationTimeByStartAt(LocalTime startAt); +} diff --git a/src/main/java/roomescape/repository/ReservationTimeRepository.java b/src/main/java/roomescape/repository/ReservationTimeRepository.java index a407c0af4c..237562ef67 100644 --- a/src/main/java/roomescape/repository/ReservationTimeRepository.java +++ b/src/main/java/roomescape/repository/ReservationTimeRepository.java @@ -1,21 +1,47 @@ package roomescape.repository; +import org.springframework.stereotype.Repository; import roomescape.model.ReservationTime; import java.time.LocalTime; import java.util.List; -public interface ReservationTimeRepository { +@Repository +public class ReservationTimeRepository { - List findAllReservationTimes(); + private final ReservationDao reservationDao; + private final ReservationTimeDao reservationTimeDao; - ReservationTime findReservationById(long id); + public ReservationTimeRepository(ReservationDao reservationDao, ReservationTimeDao reservationTimeDao) { + this.reservationDao = reservationDao; + this.reservationTimeDao = reservationTimeDao; + } - ReservationTime saveReservationTime(ReservationTime reservationTime); + public List findAllReservationTimes() { + return reservationTimeDao.findAllReservationTimes(); + } - void deleteReservationTimeById(long id); + public Long countReservationTimeByStartAt(LocalTime startAt) { + return reservationTimeDao.countReservationTimeByStartAt(startAt); + } - Long countReservationTimeById(long id); + public ReservationTime saveReservationTime(ReservationTime reservationTime) { + return reservationTimeDao.saveReservationTime(reservationTime); + } - Long countReservationTimeByStartAt(LocalTime startAt); + public ReservationTime findReservationById(long id) { + return reservationTimeDao.findReservationTimeById(id); + } + + public Long countReservationTimeById(long id) { + return reservationTimeDao.countReservationTimeById(id); + } + + public Long countReservationByTimeId(long timeId) { + return reservationDao.countReservationByTimeId(timeId); + } + + public void deleteReservationTimeById(long id) { + reservationTimeDao.deleteReservationTimeById(id); + } } diff --git a/src/main/java/roomescape/repository/ThemeDao.java b/src/main/java/roomescape/repository/ThemeDao.java new file mode 100644 index 0000000000..ba24732ae0 --- /dev/null +++ b/src/main/java/roomescape/repository/ThemeDao.java @@ -0,0 +1,19 @@ +package roomescape.repository; + +import roomescape.model.Theme; + +import java.time.LocalDate; +import java.util.List; + +public interface ThemeDao { + + List findAllThemes(); + + Theme saveTheme(Theme theme); + + void deleteThemeById(long id); + + Theme findThemeById(long id); + + List findThemeRankingByDate(LocalDate before, LocalDate after, int limit); +} diff --git a/src/main/java/roomescape/repository/ThemeRepository.java b/src/main/java/roomescape/repository/ThemeRepository.java index a812e51fff..99303e0715 100644 --- a/src/main/java/roomescape/repository/ThemeRepository.java +++ b/src/main/java/roomescape/repository/ThemeRepository.java @@ -1,19 +1,33 @@ package roomescape.repository; +import org.springframework.stereotype.Repository; import roomescape.model.Theme; import java.time.LocalDate; import java.util.List; -public interface ThemeRepository { +@Repository +public class ThemeRepository { - List findAllThemes(); + private final ThemeDao themeDao; - Theme saveTheme(Theme theme); + public ThemeRepository(ThemeDao themeDao) { + this.themeDao = themeDao; + } - void deleteThemeById(long id); + public List findAllThemes() { + return themeDao.findAllThemes(); + } - Theme findThemeById(long id); + public Theme saveTheme(Theme theme) { + return themeDao.saveTheme(theme); + } - List findThemeRankingByDate(LocalDate before, LocalDate after, int limit); + public void deleteThemeById(long id) { + themeDao.deleteThemeById(id); + } + + public List findThemeRankingByDate(LocalDate before, LocalDate after, int i) { + return themeDao.findThemeRankingByDate(before, after, 10); + } } diff --git a/src/main/java/roomescape/service/ReservationService.java b/src/main/java/roomescape/service/ReservationService.java index 682e8b26b0..a6a1cd41ac 100644 --- a/src/main/java/roomescape/service/ReservationService.java +++ b/src/main/java/roomescape/service/ReservationService.java @@ -9,8 +9,6 @@ import roomescape.model.ReservationTime; import roomescape.model.Theme; import roomescape.repository.ReservationRepository; -import roomescape.repository.ReservationTimeRepository; -import roomescape.repository.ThemeRepository; import roomescape.service.dto.ReservationDto; import java.time.LocalDate; @@ -23,15 +21,9 @@ public class ReservationService { private final ReservationRepository reservationRepository; - private final ReservationTimeRepository reservationTimeRepository; - private final ThemeRepository themeRepository; - public ReservationService(ReservationRepository reservationRepository, - ReservationTimeRepository reservationTimeRepository, - ThemeRepository themeRepository) { + public ReservationService(ReservationRepository reservationRepository) { this.reservationRepository = reservationRepository; - this.reservationTimeRepository = reservationTimeRepository; - this.themeRepository = themeRepository; } public List findAllReservations() { @@ -39,8 +31,8 @@ public List findAllReservations() { } public Reservation saveReservation(ReservationDto reservationDto) { - ReservationTime reservationTime = reservationTimeRepository.findReservationById(reservationDto.getTimeId()); - Theme theme = themeRepository.findThemeById(reservationDto.getThemeId()); + ReservationTime reservationTime = reservationRepository.findReservationTimeById(reservationDto.getTimeId()); + Theme theme = reservationRepository.findThemeById(reservationDto.getThemeId()); LocalDateTime reservationDateTime = LocalDateTime.of(reservationDto.getDate(), reservationTime.getStartAt()); @@ -66,7 +58,7 @@ public void deleteReservation(long id) { } public List findReservationTimesInformation(LocalDate date, long themeId) { - List allTimes = reservationTimeRepository.findAllReservationTimes(); + List allTimes = reservationRepository.findAllReservationTimes(); List bookedTimes = reservationRepository.findReservationTimeByDateAndThemeId(date, themeId); List notBookedTimes = filterNotBookedTimes(allTimes, bookedTimes); List bookedResponse = mapToResponse(bookedTimes, true); diff --git a/src/main/java/roomescape/service/ReservationTimeService.java b/src/main/java/roomescape/service/ReservationTimeService.java index 0a9f74f359..e012a603b8 100644 --- a/src/main/java/roomescape/service/ReservationTimeService.java +++ b/src/main/java/roomescape/service/ReservationTimeService.java @@ -5,7 +5,6 @@ import roomescape.exception.DuplicatedException; import roomescape.exception.NotFoundException; import roomescape.model.ReservationTime; -import roomescape.repository.ReservationRepository; import roomescape.repository.ReservationTimeRepository; import roomescape.service.dto.ReservationTimeDto; @@ -15,11 +14,9 @@ @Service public class ReservationTimeService { - private final ReservationRepository reservationRepository; private final ReservationTimeRepository reservationTimeRepository; - public ReservationTimeService(ReservationRepository reservationRepository, ReservationTimeRepository reservationTimeRepository) { - this.reservationRepository = reservationRepository; + public ReservationTimeService(ReservationTimeRepository reservationTimeRepository) { this.reservationTimeRepository = reservationTimeRepository; } @@ -46,7 +43,7 @@ public void deleteReservationTime(long id) { if (count == null || count <= 0) { throw new NotFoundException("[ERROR] 존재하지 않는 시간입니다."); } - Long countOfReservationUsingTime = reservationRepository.countReservationByTimeId(id); + Long countOfReservationUsingTime = reservationTimeRepository.countReservationByTimeId(id); if (countOfReservationUsingTime == null || countOfReservationUsingTime > 0) { throw new BadRequestException("[ERROR] 해당 시간을 사용하고 있는 예약이 있습니다."); } diff --git a/src/test/java/roomescape/controller/ReservationControllerTest.java b/src/test/java/roomescape/controller/ReservationControllerTest.java index 280f549c28..975c53572e 100644 --- a/src/test/java/roomescape/controller/ReservationControllerTest.java +++ b/src/test/java/roomescape/controller/ReservationControllerTest.java @@ -12,7 +12,6 @@ import roomescape.controller.request.ReservationRequest; import roomescape.controller.response.MemberReservationTimeResponse; import roomescape.controller.response.ReservationResponse; -import roomescape.model.Reservation; import java.lang.reflect.Field; import java.time.LocalDate; diff --git a/src/test/java/roomescape/controller/ThemeControllerTest.java b/src/test/java/roomescape/controller/ThemeControllerTest.java index d613c71e84..0d5b47ab03 100644 --- a/src/test/java/roomescape/controller/ThemeControllerTest.java +++ b/src/test/java/roomescape/controller/ThemeControllerTest.java @@ -2,7 +2,6 @@ import io.restassured.RestAssured; import io.restassured.http.ContentType; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -13,7 +12,6 @@ import org.springframework.test.annotation.DirtiesContext; import roomescape.controller.request.ThemeRequest; import roomescape.controller.response.ThemeResponse; -import roomescape.model.Theme; import javax.sql.DataSource; import java.time.LocalDate; @@ -23,7 +21,7 @@ import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertAll; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) diff --git a/src/test/java/roomescape/repository/ReservationDAOTest.java b/src/test/java/roomescape/repository/ReservationDAOTest.java index 24f34efe3e..fbd5a4b881 100644 --- a/src/test/java/roomescape/repository/ReservationDAOTest.java +++ b/src/test/java/roomescape/repository/ReservationDAOTest.java @@ -29,7 +29,7 @@ class ReservationDAOTest { private JdbcTemplate jdbcTemplate; @Autowired - private ReservationRepository reservationRepository; + private ReservationDao reservationDao; @Autowired private DataSource dataSource; @@ -91,14 +91,14 @@ private void insertTheme(String name, String description, String thumbnail) { @DisplayName("모든 예약을 조회한다") @Test void should_get_reservation() { - List reservations = reservationRepository.findAllReservations(); + List reservations = reservationDao.findAllReservations(); assertThat(reservations).hasSize(2); } @DisplayName("조회한 예약에 예약 시간이 존재한다.") @Test void should_get_reservation_times() { - List reservations = reservationRepository.findAllReservations(); + List reservations = reservationDao.findAllReservations(); assertThat(reservations.get(0).getTime().getStartAt()).isEqualTo(LocalTime.of(10, 0)); } @@ -109,7 +109,7 @@ void should_add_reservation() { Theme theme = new Theme(1, "에버", "공포", "공포.jpg"); Reservation reservation = new Reservation("네오", LocalDate.of(2024, 9, 1), reservationTime, theme); - reservationRepository.saveReservation(reservation); + reservationDao.saveReservation(reservation); Integer count = jdbcTemplate.queryForObject("select count(1) from reservation", Integer.class); assertThat(count).isEqualTo(3); @@ -118,7 +118,7 @@ void should_add_reservation() { @DisplayName("예약을 삭제한다") @Test void should_delete_reservation() { - reservationRepository.deleteReservationById(1); + reservationDao.deleteReservationById(1); Integer count = jdbcTemplate.queryForObject("select count(1) from reservation", Integer.class); assertThat(count).isEqualTo(1); } @@ -126,14 +126,14 @@ void should_delete_reservation() { @DisplayName("아이디가 존재하면 참을 반환한다.") @Test void should_return_true_when_id_exist() { - long count = reservationRepository.countReservationById(1); + long count = reservationDao.countReservationById(1); assertThat(count).isEqualTo(1); } @DisplayName("아이디가 존재하면 거짓을 반환한다.") @Test void should_return_false_when_id_not_exist() { - long count = reservationRepository.countReservationById(100000000); + long count = reservationDao.countReservationById(100000000); assertThat(count).isEqualTo(0); } @@ -141,7 +141,7 @@ void should_return_false_when_id_not_exist() { @Test void should_get_reservation_times_when_date_and_theme_given() { LocalDate date = LocalDate.of(2023, 8, 5); - List times = reservationRepository.findReservationTimeByDateAndThemeId(date, 1); + List times = reservationDao.findReservationTimeByDateAndThemeId(date, 1); assertThat(times).hasSize(1); assertThat(times).containsExactly(new ReservationTime(1, LocalTime.of(10, 0))); } diff --git a/src/test/java/roomescape/repository/ReservationTimeDAOTest.java b/src/test/java/roomescape/repository/ReservationTimeDAOTest.java index 13a08165a4..4f9135818e 100644 --- a/src/test/java/roomescape/repository/ReservationTimeDAOTest.java +++ b/src/test/java/roomescape/repository/ReservationTimeDAOTest.java @@ -29,7 +29,7 @@ class ReservationTimeDAOTest { private DataSource dataSource; @Autowired - private ReservationTimeRepository reservationTimeRepository; + private ReservationTimeDao reservationTimeDao; private SimpleJdbcInsert insertActor; @@ -55,14 +55,14 @@ private void insertToReservationTime(String startAt) { @DisplayName("모든 예약 시간을 조회한다") @Test void should_get_reservation_times() { - List reservationTimes = reservationTimeRepository.findAllReservationTimes(); + List reservationTimes = reservationTimeDao.findAllReservationTimes(); assertThat(reservationTimes).hasSize(2); } @DisplayName("예약 시간을 추가한다") @Test void should_add_reservation_time() { - reservationTimeRepository.saveReservationTime(new ReservationTime(LocalTime.of(12, 0))); + reservationTimeDao.saveReservationTime(new ReservationTime(LocalTime.of(12, 0))); Integer count = jdbcTemplate.queryForObject("select count(1) from reservation_time", Integer.class); assertThat(count).isEqualTo(3); } @@ -70,7 +70,7 @@ void should_add_reservation_time() { @DisplayName("예약 시간을 삭제한다") @Test void should_delete_reservation_time() { - reservationTimeRepository.deleteReservationTimeById(1); + reservationTimeDao.deleteReservationTimeById(1); Integer count = jdbcTemplate.queryForObject("select count(1) from reservation_time", Integer.class); assertThat(count).isEqualTo(1); } @@ -78,21 +78,21 @@ void should_delete_reservation_time() { @DisplayName("아이디에 해당하는 예약 시간을 조회한다.") @Test void should_get_reservation_time() { - ReservationTime reservationTime = reservationTimeRepository.findReservationById(1); + ReservationTime reservationTime = reservationTimeDao.findReservationTimeById(1); assertThat(reservationTime.getStartAt()).isEqualTo(LocalTime.of(10, 0)); } @DisplayName("아이디가 존재하면 참을 반환한다.") @Test void should_return_true_when_id_exist() { - long count = reservationTimeRepository.countReservationTimeById(1); + long count = reservationTimeDao.countReservationTimeById(1); assertThat(count).isEqualTo(1); } @DisplayName("아이디가 존재하면 거짓을 반환한다.") @Test void should_return_false_when_id_not_exist() { - long count = reservationTimeRepository.countReservationTimeById(100000000); + long count = reservationTimeDao.countReservationTimeById(100000000); assertThat(count).isEqualTo(0); } } diff --git a/src/test/java/roomescape/repository/ThemeDAOTest.java b/src/test/java/roomescape/repository/ThemeDAOTest.java index 6f4ef2c18b..fce174d9d0 100644 --- a/src/test/java/roomescape/repository/ThemeDAOTest.java +++ b/src/test/java/roomescape/repository/ThemeDAOTest.java @@ -30,7 +30,7 @@ class ThemeDAOTest { private JdbcTemplate jdbcTemplate; @Autowired - private ThemeRepository themeRepository; + private ThemeDao themeDao; private SimpleJdbcInsert themeInsertActor; private SimpleJdbcInsert reservationInsertActor; @@ -65,7 +65,7 @@ private void insertTheme(String name, String description, String thumbnail) { @DisplayName("모든 테마를 조회한다.") @Test void should_find_all_themes() { - List allThemes = themeRepository.findAllThemes(); + List allThemes = themeDao.findAllThemes(); assertThat(allThemes).hasSize(2); } @@ -73,15 +73,15 @@ void should_find_all_themes() { @Test void should_add_theme() { Theme theme = new Theme("브라운", "공포", "공포.jpg"); - themeRepository.saveTheme(theme); - assertThat(themeRepository.findAllThemes()).hasSize(3); + themeDao.saveTheme(theme); + assertThat(themeDao.findAllThemes()).hasSize(3); } @DisplayName("테마를 삭제한다.") @Test void should_delete_theme() { - themeRepository.deleteThemeById(1); - assertThat(themeRepository.findAllThemes()).hasSize(1); + themeDao.deleteThemeById(1); + assertThat(themeDao.findAllThemes()).hasSize(1); } @DisplayName("특정 기간의 테마를 인기순으로 정렬하여 조회한다.") @@ -105,7 +105,7 @@ void should_find_ranking_theme_by_date() { LocalDate before = LocalDate.of(2030, 1, 1); LocalDate after = LocalDate.of(2030, 1, 7); - List themes = themeRepository.findThemeRankingByDate(before, after, 10); + List themes = themeDao.findThemeRankingByDate(before, after, 10); assertThat(themes).hasSize(10); assertThat(themes).containsExactly( new Theme(10, "name10", "description10", "thumbnail10"), diff --git a/src/test/java/roomescape/service/FakeReservationRepository.java b/src/test/java/roomescape/service/FakeReservationDao.java similarity index 95% rename from src/test/java/roomescape/service/FakeReservationRepository.java rename to src/test/java/roomescape/service/FakeReservationDao.java index eb9a309bca..1f1e083b54 100644 --- a/src/test/java/roomescape/service/FakeReservationRepository.java +++ b/src/test/java/roomescape/service/FakeReservationDao.java @@ -3,7 +3,7 @@ import roomescape.model.Reservation; import roomescape.model.ReservationTime; import roomescape.model.Theme; -import roomescape.repository.ReservationRepository; +import roomescape.repository.ReservationDao; import java.time.LocalDate; import java.time.LocalTime; @@ -11,7 +11,7 @@ import java.util.List; import java.util.NoSuchElementException; -class FakeReservationRepository implements ReservationRepository { +class FakeReservationDao implements ReservationDao { private List reservations = new ArrayList<>(List.of( new Reservation(1, "브라운", LocalDate.of(2030, 8, 5), diff --git a/src/test/java/roomescape/service/FakeReservationTimeRepository.java b/src/test/java/roomescape/service/FakeReservationTimeDao.java similarity index 91% rename from src/test/java/roomescape/service/FakeReservationTimeRepository.java rename to src/test/java/roomescape/service/FakeReservationTimeDao.java index 87f724d08e..c9c0f37ccd 100644 --- a/src/test/java/roomescape/service/FakeReservationTimeRepository.java +++ b/src/test/java/roomescape/service/FakeReservationTimeDao.java @@ -1,14 +1,14 @@ package roomescape.service; import roomescape.model.ReservationTime; -import roomescape.repository.ReservationTimeRepository; +import roomescape.repository.ReservationTimeDao; import java.time.LocalTime; import java.util.ArrayList; import java.util.List; import java.util.NoSuchElementException; -class FakeReservationTimeRepository implements ReservationTimeRepository { +class FakeReservationTimeDao implements ReservationTimeDao { private List reservationTimes = new ArrayList<>(List.of( new ReservationTime(1, LocalTime.of(10, 0)), @@ -25,7 +25,7 @@ public List findAllReservationTimes() { } @Override - public ReservationTime findReservationById(long id) { + public ReservationTime findReservationTimeById(long id) { return reservationTimes.stream() .filter(reservationTime -> reservationTime.getId() == id) .findFirst() diff --git a/src/test/java/roomescape/service/FakeThemeRepository.java b/src/test/java/roomescape/service/FakeThemeDao.java similarity index 95% rename from src/test/java/roomescape/service/FakeThemeRepository.java rename to src/test/java/roomescape/service/FakeThemeDao.java index 87f2f13558..fc13648c95 100644 --- a/src/test/java/roomescape/service/FakeThemeRepository.java +++ b/src/test/java/roomescape/service/FakeThemeDao.java @@ -1,7 +1,7 @@ package roomescape.service; import roomescape.model.Theme; -import roomescape.repository.ThemeRepository; +import roomescape.repository.ThemeDao; import java.time.LocalDate; import java.util.ArrayList; @@ -9,7 +9,7 @@ import java.util.NoSuchElementException; import java.util.concurrent.atomic.AtomicLong; -public class FakeThemeRepository implements ThemeRepository { +public class FakeThemeDao implements ThemeDao { private List themes = new ArrayList<>(List.of( new Theme(1, "에버", "공포", "공포.jpg"), diff --git a/src/test/java/roomescape/service/ReservationServiceTest.java b/src/test/java/roomescape/service/ReservationServiceTest.java index eaf92370bd..c75d35987f 100644 --- a/src/test/java/roomescape/service/ReservationServiceTest.java +++ b/src/test/java/roomescape/service/ReservationServiceTest.java @@ -8,6 +8,8 @@ import roomescape.exception.NotFoundException; import roomescape.model.Reservation; import roomescape.model.ReservationTime; +import roomescape.repository.ReservationRepository; +import roomescape.repository.ReservationTimeDao; import roomescape.service.dto.ReservationDto; import java.time.LocalDate; @@ -18,12 +20,13 @@ class ReservationServiceTest { - private final FakeReservationTimeRepository reservationTimeRepository = new FakeReservationTimeRepository(); + private final ReservationTimeDao reservationTimeDao = new FakeReservationTimeDao(); + private final ReservationRepository reservationRepository = new ReservationRepository( + new FakeReservationDao(), reservationTimeDao, new FakeThemeDao()); +// private ReservationTimeRepository reservationTimeRepository = new ReservationTimeRepository( +// new FakeReservationDao(), new FakeReservationTimeDao()); + private final ReservationService reservationService = new ReservationService(reservationRepository); - private final ReservationService reservationService = new ReservationService( - new FakeReservationRepository(), - reservationTimeRepository, - new FakeThemeRepository()); @DisplayName("모든 예약 시간을 반환한다") @Test @@ -76,7 +79,7 @@ void should_throw_exception_when_previous_date() { @DisplayName("현재로 예약하면 예외가 발생하지 않는다.") @Test void should_not_throw_exception_when_current_date() { - reservationTimeRepository.add(new ReservationTime(3, LocalTime.now())); + reservationTimeDao.saveReservationTime(new ReservationTime(3, LocalTime.now())); ReservationDto request = new ReservationDto("에버", LocalDate.now(), 3L, 1L); assertThatCode(() -> reservationService.saveReservation(request)) .doesNotThrowAnyException(); diff --git a/src/test/java/roomescape/service/ReservationTimeServiceTest.java b/src/test/java/roomescape/service/ReservationTimeServiceTest.java index 5f2e9cf63a..102bb843df 100644 --- a/src/test/java/roomescape/service/ReservationTimeServiceTest.java +++ b/src/test/java/roomescape/service/ReservationTimeServiceTest.java @@ -6,6 +6,7 @@ import roomescape.exception.DuplicatedException; import roomescape.exception.NotFoundException; import roomescape.model.ReservationTime; +import roomescape.repository.ReservationTimeRepository; import roomescape.service.dto.ReservationTimeDto; import java.time.LocalTime; @@ -15,10 +16,10 @@ class ReservationTimeServiceTest { - private final ReservationTimeService reservationTimeService = new ReservationTimeService( - new FakeReservationRepository(), - new FakeReservationTimeRepository() - ); + private final ReservationTimeRepository reservationTimeRepository = new ReservationTimeRepository( + new FakeReservationDao(), new FakeReservationTimeDao()); + + private final ReservationTimeService reservationTimeService = new ReservationTimeService(reservationTimeRepository); @DisplayName("모든 예약 시간을 반환한다") @Test diff --git a/src/test/java/roomescape/service/ThemeServiceTest.java b/src/test/java/roomescape/service/ThemeServiceTest.java index af06633619..818e673a6b 100644 --- a/src/test/java/roomescape/service/ThemeServiceTest.java +++ b/src/test/java/roomescape/service/ThemeServiceTest.java @@ -3,6 +3,7 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import roomescape.model.Theme; +import roomescape.repository.ThemeRepository; import roomescape.service.dto.ThemeDto; import java.util.List; @@ -11,7 +12,8 @@ class ThemeServiceTest { - private final ThemeService themeService = new ThemeService(new FakeThemeRepository()); + private final ThemeRepository themeRepository = new ThemeRepository(new FakeThemeDao()); + private final ThemeService themeService = new ThemeService(themeRepository); @DisplayName("테마를 조회한다.") @Test From a00a9c3d8f4d531193eb3bdba29d321605ca79ed Mon Sep 17 00:00:00 2001 From: SCY Date: Fri, 3 May 2024 16:43:06 +0900 Subject: [PATCH 42/74] =?UTF-8?q?chore(dao):=20dao=20=EA=B3=84=EC=B8=B5=20?= =?UTF-8?q?=ED=8C=A8=ED=82=A4=EC=A7=80=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/roomescape/repository/ReservationRepository.java | 3 +++ .../java/roomescape/repository/ReservationTimeRepository.java | 2 ++ src/main/java/roomescape/repository/ThemeRepository.java | 1 + .../roomescape/repository/{ => dao}/JdbcReservationDao.java | 2 +- .../repository/{ => dao}/JdbcReservationTimeDao.java | 2 +- .../java/roomescape/repository/{ => dao}/JdbcThemeDao.java | 2 +- .../java/roomescape/repository/{ => dao}/ReservationDao.java | 2 +- .../roomescape/repository/{ => dao}/ReservationTimeDao.java | 2 +- src/main/java/roomescape/repository/{ => dao}/ThemeDao.java | 2 +- src/test/java/roomescape/repository/ReservationDAOTest.java | 1 + .../java/roomescape/repository/ReservationTimeDAOTest.java | 1 + src/test/java/roomescape/repository/ThemeDAOTest.java | 1 + src/test/java/roomescape/service/FakeReservationDao.java | 2 +- src/test/java/roomescape/service/FakeReservationTimeDao.java | 2 +- src/test/java/roomescape/service/FakeThemeDao.java | 2 +- src/test/java/roomescape/service/ReservationServiceTest.java | 2 +- 16 files changed, 19 insertions(+), 10 deletions(-) rename src/main/java/roomescape/repository/{ => dao}/JdbcReservationDao.java (99%) rename src/main/java/roomescape/repository/{ => dao}/JdbcReservationTimeDao.java (98%) rename src/main/java/roomescape/repository/{ => dao}/JdbcThemeDao.java (98%) rename src/main/java/roomescape/repository/{ => dao}/ReservationDao.java (94%) rename src/main/java/roomescape/repository/{ => dao}/ReservationTimeDao.java (93%) rename src/main/java/roomescape/repository/{ => dao}/ThemeDao.java (90%) diff --git a/src/main/java/roomescape/repository/ReservationRepository.java b/src/main/java/roomescape/repository/ReservationRepository.java index c8d387f9a6..ddd8b2bb27 100644 --- a/src/main/java/roomescape/repository/ReservationRepository.java +++ b/src/main/java/roomescape/repository/ReservationRepository.java @@ -4,6 +4,9 @@ import roomescape.model.Reservation; import roomescape.model.ReservationTime; import roomescape.model.Theme; +import roomescape.repository.dao.ReservationDao; +import roomescape.repository.dao.ReservationTimeDao; +import roomescape.repository.dao.ThemeDao; import java.time.LocalDate; import java.util.List; diff --git a/src/main/java/roomescape/repository/ReservationTimeRepository.java b/src/main/java/roomescape/repository/ReservationTimeRepository.java index 237562ef67..d75e67a616 100644 --- a/src/main/java/roomescape/repository/ReservationTimeRepository.java +++ b/src/main/java/roomescape/repository/ReservationTimeRepository.java @@ -2,6 +2,8 @@ import org.springframework.stereotype.Repository; import roomescape.model.ReservationTime; +import roomescape.repository.dao.ReservationDao; +import roomescape.repository.dao.ReservationTimeDao; import java.time.LocalTime; import java.util.List; diff --git a/src/main/java/roomescape/repository/ThemeRepository.java b/src/main/java/roomescape/repository/ThemeRepository.java index 99303e0715..3070cc2491 100644 --- a/src/main/java/roomescape/repository/ThemeRepository.java +++ b/src/main/java/roomescape/repository/ThemeRepository.java @@ -2,6 +2,7 @@ import org.springframework.stereotype.Repository; import roomescape.model.Theme; +import roomescape.repository.dao.ThemeDao; import java.time.LocalDate; import java.util.List; diff --git a/src/main/java/roomescape/repository/JdbcReservationDao.java b/src/main/java/roomescape/repository/dao/JdbcReservationDao.java similarity index 99% rename from src/main/java/roomescape/repository/JdbcReservationDao.java rename to src/main/java/roomescape/repository/dao/JdbcReservationDao.java index 3bbc7ad0b4..80890fdbf8 100644 --- a/src/main/java/roomescape/repository/JdbcReservationDao.java +++ b/src/main/java/roomescape/repository/dao/JdbcReservationDao.java @@ -1,4 +1,4 @@ -package roomescape.repository; +package roomescape.repository.dao; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.simple.SimpleJdbcInsert; diff --git a/src/main/java/roomescape/repository/JdbcReservationTimeDao.java b/src/main/java/roomescape/repository/dao/JdbcReservationTimeDao.java similarity index 98% rename from src/main/java/roomescape/repository/JdbcReservationTimeDao.java rename to src/main/java/roomescape/repository/dao/JdbcReservationTimeDao.java index cbbdaf486d..27f518c5a6 100644 --- a/src/main/java/roomescape/repository/JdbcReservationTimeDao.java +++ b/src/main/java/roomescape/repository/dao/JdbcReservationTimeDao.java @@ -1,4 +1,4 @@ -package roomescape.repository; +package roomescape.repository.dao; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.simple.SimpleJdbcInsert; diff --git a/src/main/java/roomescape/repository/JdbcThemeDao.java b/src/main/java/roomescape/repository/dao/JdbcThemeDao.java similarity index 98% rename from src/main/java/roomescape/repository/JdbcThemeDao.java rename to src/main/java/roomescape/repository/dao/JdbcThemeDao.java index a9c7988bbd..b54ccff196 100644 --- a/src/main/java/roomescape/repository/JdbcThemeDao.java +++ b/src/main/java/roomescape/repository/dao/JdbcThemeDao.java @@ -1,4 +1,4 @@ -package roomescape.repository; +package roomescape.repository.dao; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.simple.SimpleJdbcInsert; diff --git a/src/main/java/roomescape/repository/ReservationDao.java b/src/main/java/roomescape/repository/dao/ReservationDao.java similarity index 94% rename from src/main/java/roomescape/repository/ReservationDao.java rename to src/main/java/roomescape/repository/dao/ReservationDao.java index dae8ccac4a..cf15fb3a52 100644 --- a/src/main/java/roomescape/repository/ReservationDao.java +++ b/src/main/java/roomescape/repository/dao/ReservationDao.java @@ -1,4 +1,4 @@ -package roomescape.repository; +package roomescape.repository.dao; import roomescape.model.Reservation; import roomescape.model.ReservationTime; diff --git a/src/main/java/roomescape/repository/ReservationTimeDao.java b/src/main/java/roomescape/repository/dao/ReservationTimeDao.java similarity index 93% rename from src/main/java/roomescape/repository/ReservationTimeDao.java rename to src/main/java/roomescape/repository/dao/ReservationTimeDao.java index 59015d3fe4..426ea5c301 100644 --- a/src/main/java/roomescape/repository/ReservationTimeDao.java +++ b/src/main/java/roomescape/repository/dao/ReservationTimeDao.java @@ -1,4 +1,4 @@ -package roomescape.repository; +package roomescape.repository.dao; import roomescape.model.ReservationTime; diff --git a/src/main/java/roomescape/repository/ThemeDao.java b/src/main/java/roomescape/repository/dao/ThemeDao.java similarity index 90% rename from src/main/java/roomescape/repository/ThemeDao.java rename to src/main/java/roomescape/repository/dao/ThemeDao.java index ba24732ae0..f79503fa90 100644 --- a/src/main/java/roomescape/repository/ThemeDao.java +++ b/src/main/java/roomescape/repository/dao/ThemeDao.java @@ -1,4 +1,4 @@ -package roomescape.repository; +package roomescape.repository.dao; import roomescape.model.Theme; diff --git a/src/test/java/roomescape/repository/ReservationDAOTest.java b/src/test/java/roomescape/repository/ReservationDAOTest.java index fbd5a4b881..a052a8b5c9 100644 --- a/src/test/java/roomescape/repository/ReservationDAOTest.java +++ b/src/test/java/roomescape/repository/ReservationDAOTest.java @@ -11,6 +11,7 @@ import roomescape.model.Reservation; import roomescape.model.ReservationTime; import roomescape.model.Theme; +import roomescape.repository.dao.ReservationDao; import javax.sql.DataSource; import java.time.LocalDate; diff --git a/src/test/java/roomescape/repository/ReservationTimeDAOTest.java b/src/test/java/roomescape/repository/ReservationTimeDAOTest.java index 4f9135818e..a5ccb12ce5 100644 --- a/src/test/java/roomescape/repository/ReservationTimeDAOTest.java +++ b/src/test/java/roomescape/repository/ReservationTimeDAOTest.java @@ -9,6 +9,7 @@ import org.springframework.jdbc.core.simple.SimpleJdbcInsert; import org.springframework.test.annotation.DirtiesContext; import roomescape.model.ReservationTime; +import roomescape.repository.dao.ReservationTimeDao; import javax.sql.DataSource; import java.time.LocalTime; diff --git a/src/test/java/roomescape/repository/ThemeDAOTest.java b/src/test/java/roomescape/repository/ThemeDAOTest.java index fce174d9d0..d6fb08e632 100644 --- a/src/test/java/roomescape/repository/ThemeDAOTest.java +++ b/src/test/java/roomescape/repository/ThemeDAOTest.java @@ -9,6 +9,7 @@ import org.springframework.jdbc.core.simple.SimpleJdbcInsert; import org.springframework.test.annotation.DirtiesContext; import roomescape.model.Theme; +import roomescape.repository.dao.ThemeDao; import javax.sql.DataSource; import java.time.LocalDate; diff --git a/src/test/java/roomescape/service/FakeReservationDao.java b/src/test/java/roomescape/service/FakeReservationDao.java index 1f1e083b54..a8f4734c52 100644 --- a/src/test/java/roomescape/service/FakeReservationDao.java +++ b/src/test/java/roomescape/service/FakeReservationDao.java @@ -3,7 +3,7 @@ import roomescape.model.Reservation; import roomescape.model.ReservationTime; import roomescape.model.Theme; -import roomescape.repository.ReservationDao; +import roomescape.repository.dao.ReservationDao; import java.time.LocalDate; import java.time.LocalTime; diff --git a/src/test/java/roomescape/service/FakeReservationTimeDao.java b/src/test/java/roomescape/service/FakeReservationTimeDao.java index c9c0f37ccd..b39683b9ad 100644 --- a/src/test/java/roomescape/service/FakeReservationTimeDao.java +++ b/src/test/java/roomescape/service/FakeReservationTimeDao.java @@ -1,7 +1,7 @@ package roomescape.service; import roomescape.model.ReservationTime; -import roomescape.repository.ReservationTimeDao; +import roomescape.repository.dao.ReservationTimeDao; import java.time.LocalTime; import java.util.ArrayList; diff --git a/src/test/java/roomescape/service/FakeThemeDao.java b/src/test/java/roomescape/service/FakeThemeDao.java index fc13648c95..ff3c03137e 100644 --- a/src/test/java/roomescape/service/FakeThemeDao.java +++ b/src/test/java/roomescape/service/FakeThemeDao.java @@ -1,7 +1,7 @@ package roomescape.service; import roomescape.model.Theme; -import roomescape.repository.ThemeDao; +import roomescape.repository.dao.ThemeDao; import java.time.LocalDate; import java.util.ArrayList; diff --git a/src/test/java/roomescape/service/ReservationServiceTest.java b/src/test/java/roomescape/service/ReservationServiceTest.java index c75d35987f..7218fe2c21 100644 --- a/src/test/java/roomescape/service/ReservationServiceTest.java +++ b/src/test/java/roomescape/service/ReservationServiceTest.java @@ -9,7 +9,7 @@ import roomescape.model.Reservation; import roomescape.model.ReservationTime; import roomescape.repository.ReservationRepository; -import roomescape.repository.ReservationTimeDao; +import roomescape.repository.dao.ReservationTimeDao; import roomescape.service.dto.ReservationDto; import java.time.LocalDate; From 5cc17d863df0579670c312046779bc4508b36c8d Mon Sep 17 00:00:00 2001 From: SCY Date: Fri, 3 May 2024 16:47:33 +0900 Subject: [PATCH 43/74] =?UTF-8?q?refactor(all):=20=EB=B6=88=ED=95=84?= =?UTF-8?q?=EC=9A=94=ED=95=9C=20dataSource=20=EA=B0=9D=EC=B2=B4=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../roomescape/repository/dao/JdbcReservationDao.java | 6 +++--- .../repository/dao/JdbcReservationTimeDao.java | 6 +++--- .../java/roomescape/repository/dao/JdbcThemeDao.java | 6 +++--- .../java/roomescape/controller/ThemeControllerTest.java | 9 +++------ .../java/roomescape/repository/ReservationDAOTest.java | 9 +++------ .../roomescape/repository/ReservationTimeDAOTest.java | 5 +---- src/test/java/roomescape/repository/ThemeDAOTest.java | 9 +++------ 7 files changed, 19 insertions(+), 31 deletions(-) diff --git a/src/main/java/roomescape/repository/dao/JdbcReservationDao.java b/src/main/java/roomescape/repository/dao/JdbcReservationDao.java index 80890fdbf8..b7ccf2f41f 100644 --- a/src/main/java/roomescape/repository/dao/JdbcReservationDao.java +++ b/src/main/java/roomescape/repository/dao/JdbcReservationDao.java @@ -18,11 +18,11 @@ public class JdbcReservationDao implements ReservationDao { private final JdbcTemplate jdbcTemplate; - private SimpleJdbcInsert insertActor; + private final SimpleJdbcInsert insertActor; - public JdbcReservationDao(JdbcTemplate jdbcTemplate, DataSource dataSource) { + public JdbcReservationDao(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; - this.insertActor = new SimpleJdbcInsert(dataSource) + this.insertActor = new SimpleJdbcInsert(jdbcTemplate) .withTableName("reservation") .usingGeneratedKeyColumns("id"); } diff --git a/src/main/java/roomescape/repository/dao/JdbcReservationTimeDao.java b/src/main/java/roomescape/repository/dao/JdbcReservationTimeDao.java index 27f518c5a6..b6f38f967b 100644 --- a/src/main/java/roomescape/repository/dao/JdbcReservationTimeDao.java +++ b/src/main/java/roomescape/repository/dao/JdbcReservationTimeDao.java @@ -16,11 +16,11 @@ public class JdbcReservationTimeDao implements ReservationTimeDao { private final JdbcTemplate jdbcTemplate; - private SimpleJdbcInsert insertActor; + private final SimpleJdbcInsert insertActor; - public JdbcReservationTimeDao(JdbcTemplate jdbcTemplate, DataSource dataSource) { + public JdbcReservationTimeDao(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; - this.insertActor = new SimpleJdbcInsert(dataSource) + this.insertActor = new SimpleJdbcInsert(jdbcTemplate) .withTableName("reservation_time") .usingGeneratedKeyColumns("id"); } diff --git a/src/main/java/roomescape/repository/dao/JdbcThemeDao.java b/src/main/java/roomescape/repository/dao/JdbcThemeDao.java index b54ccff196..e030a8ad79 100644 --- a/src/main/java/roomescape/repository/dao/JdbcThemeDao.java +++ b/src/main/java/roomescape/repository/dao/JdbcThemeDao.java @@ -15,11 +15,11 @@ public class JdbcThemeDao implements ThemeDao { private final JdbcTemplate jdbcTemplate; - private SimpleJdbcInsert insertActor; + private final SimpleJdbcInsert insertActor; - public JdbcThemeDao(JdbcTemplate jdbcTemplate, DataSource dataSource) { + public JdbcThemeDao(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; - this.insertActor = new SimpleJdbcInsert(dataSource) + this.insertActor = new SimpleJdbcInsert(jdbcTemplate) .withTableName("theme") .usingGeneratedKeyColumns("id"); } diff --git a/src/test/java/roomescape/controller/ThemeControllerTest.java b/src/test/java/roomescape/controller/ThemeControllerTest.java index 0d5b47ab03..8f837edaa6 100644 --- a/src/test/java/roomescape/controller/ThemeControllerTest.java +++ b/src/test/java/roomescape/controller/ThemeControllerTest.java @@ -27,9 +27,6 @@ @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) class ThemeControllerTest { - @Autowired - private DataSource dataSource; - @Autowired private JdbcTemplate jdbcTemplate; @@ -39,13 +36,13 @@ class ThemeControllerTest { @BeforeEach void setUp() { - reservationInsertActor = new SimpleJdbcInsert(dataSource) + reservationInsertActor = new SimpleJdbcInsert(jdbcTemplate) .withTableName("reservation") .usingGeneratedKeyColumns("id"); - timeInsertActor = new SimpleJdbcInsert(dataSource) + timeInsertActor = new SimpleJdbcInsert(jdbcTemplate) .withTableName("reservation_time") .usingGeneratedKeyColumns("id"); - themeInsertActor = new SimpleJdbcInsert(dataSource) + themeInsertActor = new SimpleJdbcInsert(jdbcTemplate) .withTableName("theme") .usingGeneratedKeyColumns("id"); } diff --git a/src/test/java/roomescape/repository/ReservationDAOTest.java b/src/test/java/roomescape/repository/ReservationDAOTest.java index a052a8b5c9..a9ecd73dc0 100644 --- a/src/test/java/roomescape/repository/ReservationDAOTest.java +++ b/src/test/java/roomescape/repository/ReservationDAOTest.java @@ -32,9 +32,6 @@ class ReservationDAOTest { @Autowired private ReservationDao reservationDao; - @Autowired - private DataSource dataSource; - private SimpleJdbcInsert reservationTimeInsertActor; private SimpleJdbcInsert reservationInsertActor; private SimpleJdbcInsert themeInsertActor; @@ -46,13 +43,13 @@ void setUp() { jdbcTemplate.execute("TRUNCATE TABLE reservation_time RESTART IDENTITY"); jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY TRUE"); - reservationTimeInsertActor = new SimpleJdbcInsert(dataSource) + reservationTimeInsertActor = new SimpleJdbcInsert(jdbcTemplate) .withTableName("reservation_time") .usingGeneratedKeyColumns("id"); - reservationInsertActor = new SimpleJdbcInsert(dataSource) + reservationInsertActor = new SimpleJdbcInsert(jdbcTemplate) .withTableName("reservation") .usingGeneratedKeyColumns("id"); - themeInsertActor = new SimpleJdbcInsert(dataSource) + themeInsertActor = new SimpleJdbcInsert(jdbcTemplate) .withTableName("theme") .usingGeneratedKeyColumns("id"); diff --git a/src/test/java/roomescape/repository/ReservationTimeDAOTest.java b/src/test/java/roomescape/repository/ReservationTimeDAOTest.java index a5ccb12ce5..b94ada7fbd 100644 --- a/src/test/java/roomescape/repository/ReservationTimeDAOTest.java +++ b/src/test/java/roomescape/repository/ReservationTimeDAOTest.java @@ -26,9 +26,6 @@ class ReservationTimeDAOTest { @Autowired private JdbcTemplate jdbcTemplate; - @Autowired - private DataSource dataSource; - @Autowired private ReservationTimeDao reservationTimeDao; @@ -40,7 +37,7 @@ void setUp() { jdbcTemplate.execute("TRUNCATE TABLE reservation_time RESTART IDENTITY"); jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY TRUE"); - insertActor = new SimpleJdbcInsert(dataSource) + insertActor = new SimpleJdbcInsert(jdbcTemplate) .withTableName("reservation_time") .usingGeneratedKeyColumns("id"); insertToReservationTime("10:00"); diff --git a/src/test/java/roomescape/repository/ThemeDAOTest.java b/src/test/java/roomescape/repository/ThemeDAOTest.java index d6fb08e632..1766911adb 100644 --- a/src/test/java/roomescape/repository/ThemeDAOTest.java +++ b/src/test/java/roomescape/repository/ThemeDAOTest.java @@ -24,9 +24,6 @@ @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) class ThemeDAOTest { - @Autowired - private DataSource dataSource; - @Autowired private JdbcTemplate jdbcTemplate; @@ -42,13 +39,13 @@ void setUp() { jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY FALSE"); jdbcTemplate.execute("TRUNCATE TABLE theme RESTART IDENTITY"); jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY TRUE"); - themeInsertActor = new SimpleJdbcInsert(dataSource) + themeInsertActor = new SimpleJdbcInsert(jdbcTemplate) .withTableName("theme") .usingGeneratedKeyColumns("id"); - reservationInsertActor = new SimpleJdbcInsert(dataSource) + reservationInsertActor = new SimpleJdbcInsert(jdbcTemplate) .withTableName("reservation") .usingGeneratedKeyColumns("id"); - timeInsertActor = new SimpleJdbcInsert(dataSource) + timeInsertActor = new SimpleJdbcInsert(jdbcTemplate) .withTableName("reservation_time") .usingGeneratedKeyColumns("id"); insertTheme("에버", "공포", "공포.jpg"); From 19eac9216599267862e36cfab01af09d89347922 Mon Sep 17 00:00:00 2001 From: SCY Date: Fri, 3 May 2024 16:52:16 +0900 Subject: [PATCH 44/74] =?UTF-8?q?fix(ReservationTimeController):=20?= =?UTF-8?q?=EB=8B=A4=EB=A5=B8=20=EC=83=81=ED=83=9C=EC=BD=94=EB=93=9C?= =?UTF-8?q?=EB=A1=9C=20=EC=9D=B8=ED=95=9C=20=EB=A0=8C=EB=8D=94=EB=A7=81=20?= =?UTF-8?q?=EB=B6=88=EA=B0=80=20=EB=AC=B8=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/roomescape/controller/ReservationTimeController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/roomescape/controller/ReservationTimeController.java b/src/main/java/roomescape/controller/ReservationTimeController.java index d0f2dfc6dc..604393ea73 100644 --- a/src/main/java/roomescape/controller/ReservationTimeController.java +++ b/src/main/java/roomescape/controller/ReservationTimeController.java @@ -43,6 +43,6 @@ public ResponseEntity addReservationTime(@RequestBody R @DeleteMapping("/{id}") public ResponseEntity deleteReservationTime(@PathVariable("id") long id) { reservationTimeService.deleteReservationTime(id); - return ResponseEntity.ok().build(); + return ResponseEntity.noContent().build(); } } From ae3078011e50854208b683d6c8a6e73808258f37 Mon Sep 17 00:00:00 2001 From: SCY Date: Fri, 3 May 2024 16:52:48 +0900 Subject: [PATCH 45/74] =?UTF-8?q?fix(ReservationResponse):=20=EB=8B=A4?= =?UTF-8?q?=EB=A5=B8=20=ED=95=84=EB=93=9C=EB=AA=85=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EC=9D=B8=ED=95=9C=20=ED=8C=8C=EC=8B=B1=20=EB=B6=88=EA=B0=80=20?= =?UTF-8?q?=EB=AC=B8=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../response/ReservationResponse.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/java/roomescape/controller/response/ReservationResponse.java b/src/main/java/roomescape/controller/response/ReservationResponse.java index ec80d5e5fb..65950c4026 100644 --- a/src/main/java/roomescape/controller/response/ReservationResponse.java +++ b/src/main/java/roomescape/controller/response/ReservationResponse.java @@ -11,15 +11,15 @@ public class ReservationResponse { private final long id; private final String name; private final LocalDate date; - private final ReservationTimeResponse timeResponse; - private final ThemeResponse themeResponse; + private final ReservationTimeResponse time; + private final ThemeResponse theme; - private ReservationResponse(long id, String name, LocalDate date, ReservationTimeResponse timeResponse, ThemeResponse themeResponse) { + private ReservationResponse(long id, String name, LocalDate date, ReservationTimeResponse time, ThemeResponse theme) { this.id = id; this.name = name; this.date = date; - this.timeResponse = timeResponse; - this.themeResponse = themeResponse; + this.time = time; + this.theme = theme; } // TODO: if private, cannot parse? public static ReservationResponse from(Reservation reservation) { @@ -42,11 +42,11 @@ public LocalDate getDate() { return date; } - public ReservationTimeResponse getTimeResponse() { - return timeResponse; + public ReservationTimeResponse getTime() { + return time; } - public ThemeResponse getThemeResponse() { - return themeResponse; + public ThemeResponse getTheme() { + return theme; } } From 767ccdd77027fcca5304367ea3462ca3469f62ae Mon Sep 17 00:00:00 2001 From: SCY Date: Fri, 3 May 2024 18:03:09 +0900 Subject: [PATCH 46/74] =?UTF-8?q?refactor(ReservationService):=20=EB=B6=88?= =?UTF-8?q?=ED=95=84=EC=9A=94=ED=95=9C=20=EB=A1=9C=EC=A7=81=20=EC=A4=84?= =?UTF-8?q?=EC=9D=B4=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../roomescape/model/ReservationTime.java | 8 ++++ .../repository/ReservationRepository.java | 8 ++-- .../repository/dao/JdbcReservationDao.java | 19 +++++++- .../repository/dao/ReservationDao.java | 4 +- .../service/ReservationService.java | 47 ++++++++++++------- .../ReservationTimeControllerTest.java | 2 +- ...onDAOTest.java => ReservationDaoTest.java} | 5 +- ...OTest.java => ReservationTimeDaoTest.java} | 3 +- .../{ThemeDAOTest.java => ThemeDaoTest.java} | 3 +- .../service/FakeReservationDao.java | 13 ++++- .../service/ReservationServiceTest.java | 3 +- 11 files changed, 81 insertions(+), 34 deletions(-) rename src/test/java/roomescape/repository/{ReservationDAOTest.java => ReservationDaoTest.java} (98%) rename src/test/java/roomescape/repository/{ReservationTimeDAOTest.java => ReservationTimeDaoTest.java} (98%) rename src/test/java/roomescape/repository/{ThemeDAOTest.java => ThemeDaoTest.java} (99%) diff --git a/src/main/java/roomescape/model/ReservationTime.java b/src/main/java/roomescape/model/ReservationTime.java index 4dc4e0d080..c174f501ab 100644 --- a/src/main/java/roomescape/model/ReservationTime.java +++ b/src/main/java/roomescape/model/ReservationTime.java @@ -40,4 +40,12 @@ public boolean equals(Object o) { public int hashCode() { return Objects.hash(id, startAt); } + + @Override + public String toString() { + return "ReservationTime{" + + "id=" + id + + ", startAt=" + startAt + + '}'; + } } diff --git a/src/main/java/roomescape/repository/ReservationRepository.java b/src/main/java/roomescape/repository/ReservationRepository.java index ddd8b2bb27..b35bff681a 100644 --- a/src/main/java/roomescape/repository/ReservationRepository.java +++ b/src/main/java/roomescape/repository/ReservationRepository.java @@ -52,11 +52,11 @@ public void deleteReservationById(long id) { reservationDao.deleteReservationById(id); } - public List findAllReservationTimes() { - return reservationTimeDao.findAllReservationTimes(); + public List findReservationTimeBooked(LocalDate date, long themeId) { + return reservationDao.findReservationTimeBooked(date, themeId); } - public List findReservationTimeByDateAndThemeId(LocalDate date, long themeId) { - return reservationDao.findReservationTimeByDateAndThemeId(date, themeId); + public List findReservationTimeNotBooked(LocalDate date, long themeId) { + return reservationDao.findReservationTimeNotBooked(date, themeId); } } diff --git a/src/main/java/roomescape/repository/dao/JdbcReservationDao.java b/src/main/java/roomescape/repository/dao/JdbcReservationDao.java index b7ccf2f41f..959be4d5b6 100644 --- a/src/main/java/roomescape/repository/dao/JdbcReservationDao.java +++ b/src/main/java/roomescape/repository/dao/JdbcReservationDao.java @@ -98,7 +98,24 @@ public Long countReservationByDateAndTimeId(LocalDate date, long timeId) { } @Override - public List findReservationTimeByDateAndThemeId(LocalDate date, long themeId) { + public List findReservationTimeNotBooked(LocalDate date, long themeId) { + String sql = """ + select t.id as time_id, t.start_at as start_at + from reservation_time as t + minus + select t.id as time_id, t.start_at as start_at + from reservation as r inner join reservation_time as t on r.time_id = t.id + where date = ? and theme_id = ? + """; + return jdbcTemplate.query(sql, (resultSet, rowNum) -> + new ReservationTime( + resultSet.getLong("time_id"), + resultSet.getTime("start_at").toLocalTime() + ), date, themeId); + } + + @Override + public List findReservationTimeBooked(LocalDate date, long themeId) { String sql = """ select t.id as time_id, t.start_at as start_at from reservation as r inner join reservation_time as t on r.time_id = t.id diff --git a/src/main/java/roomescape/repository/dao/ReservationDao.java b/src/main/java/roomescape/repository/dao/ReservationDao.java index cf15fb3a52..4b043d1f16 100644 --- a/src/main/java/roomescape/repository/dao/ReservationDao.java +++ b/src/main/java/roomescape/repository/dao/ReservationDao.java @@ -20,5 +20,7 @@ public interface ReservationDao { Long countReservationByDateAndTimeId(LocalDate date, long timeId); - List findReservationTimeByDateAndThemeId(LocalDate date, long themeId); + List findReservationTimeBooked(LocalDate date, long themeId); + + List findReservationTimeNotBooked(LocalDate date, long themeId); } diff --git a/src/main/java/roomescape/service/ReservationService.java b/src/main/java/roomescape/service/ReservationService.java index a6a1cd41ac..2a88a8361a 100644 --- a/src/main/java/roomescape/service/ReservationService.java +++ b/src/main/java/roomescape/service/ReservationService.java @@ -31,47 +31,58 @@ public List findAllReservations() { } public Reservation saveReservation(ReservationDto reservationDto) { - ReservationTime reservationTime = reservationRepository.findReservationTimeById(reservationDto.getTimeId()); - Theme theme = reservationRepository.findThemeById(reservationDto.getThemeId()); + String name = reservationDto.getName(); + LocalDate date = reservationDto.getDate(); + long timeId = reservationDto.getTimeId(); + long themeId = reservationDto.getThemeId(); + ReservationTime time = reservationRepository.findReservationTimeById(timeId); + Theme theme = reservationRepository.findThemeById(themeId); - LocalDateTime reservationDateTime = LocalDateTime.of(reservationDto.getDate(), reservationTime.getStartAt()); + validate(date, time); + Reservation reservation = new Reservation(name, date, time, theme); + return reservationRepository.saveReservation(reservation); + } + + private void validate(LocalDate date, ReservationTime time) { + validateDateTime(date, time); + validateDuplication(date, time.getId()); + } - LocalDateTime requestDateTime = reservationDateTime.truncatedTo(ChronoUnit.SECONDS); + private void validateDateTime(LocalDate date, ReservationTime time) { LocalDateTime now = LocalDateTime.now().truncatedTo(ChronoUnit.SECONDS); - if (requestDateTime.isBefore(now)) { + LocalDateTime dateTime = LocalDateTime.of(date, time.getStartAt()).truncatedTo(ChronoUnit.SECONDS); + if (dateTime.isBefore(now)) { throw new BadRequestException("[ERROR] 현재 이전 예약은 할 수 없습니다."); } - Long countReservation = reservationRepository.countReservationByDateAndTimeId(reservationDto.getDate(), reservationDto.getTimeId()); + } + + private void validateDuplication(LocalDate date, long timeId) { + Long countReservation = reservationRepository.countReservationByDateAndTimeId(date, timeId); if (countReservation == null || countReservation > 0) { throw new DuplicatedException("[ERROR] 중복되는 예약은 추가할 수 없습니다."); } - Reservation reservation = new Reservation(reservationDto.getName(), reservationDto.getDate(), reservationTime, theme); - return reservationRepository.saveReservation(reservation); } public void deleteReservation(long id) { + validateExistence(id); + reservationRepository.deleteReservationById(id); + } + + private void validateExistence(long id) { Long count = reservationRepository.countReservationById(id); if (count == null || count <= 0) { throw new NotFoundException("[ERROR] 존재하지 않는 예약입니다."); } - reservationRepository.deleteReservationById(id); } public List findReservationTimesInformation(LocalDate date, long themeId) { - List allTimes = reservationRepository.findAllReservationTimes(); - List bookedTimes = reservationRepository.findReservationTimeByDateAndThemeId(date, themeId); - List notBookedTimes = filterNotBookedTimes(allTimes, bookedTimes); + List bookedTimes = reservationRepository.findReservationTimeBooked(date, themeId); + List notBookedTimes = reservationRepository.findReservationTimeNotBooked(date, themeId); List bookedResponse = mapToResponse(bookedTimes, true); List notBookedResponse = mapToResponse(notBookedTimes, false); return concat(notBookedResponse, bookedResponse); } - private List filterNotBookedTimes(List allTimes, List bookedTimes) { - return allTimes.stream() - .filter(time -> !bookedTimes.contains(time)) - .toList(); - } - private List mapToResponse(List times, boolean isBooked) { return times.stream() .map(time -> new MemberReservationTimeResponse(time.getId(), time.getStartAt(), isBooked)) diff --git a/src/test/java/roomescape/controller/ReservationTimeControllerTest.java b/src/test/java/roomescape/controller/ReservationTimeControllerTest.java index a89f37cf35..b03d360db4 100644 --- a/src/test/java/roomescape/controller/ReservationTimeControllerTest.java +++ b/src/test/java/roomescape/controller/ReservationTimeControllerTest.java @@ -63,7 +63,7 @@ void should_remove_reservation_time() { RestAssured.given().log().all() .when().delete("/times/1") .then().log().all() - .statusCode(200); + .statusCode(204); Integer count = jdbcTemplate.queryForObject("SELECT count(1) from reservation_time", Integer.class); assertThat(count).isEqualTo(1); diff --git a/src/test/java/roomescape/repository/ReservationDAOTest.java b/src/test/java/roomescape/repository/ReservationDaoTest.java similarity index 98% rename from src/test/java/roomescape/repository/ReservationDAOTest.java rename to src/test/java/roomescape/repository/ReservationDaoTest.java index a9ecd73dc0..cb003d8b15 100644 --- a/src/test/java/roomescape/repository/ReservationDAOTest.java +++ b/src/test/java/roomescape/repository/ReservationDaoTest.java @@ -13,7 +13,6 @@ import roomescape.model.Theme; import roomescape.repository.dao.ReservationDao; -import javax.sql.DataSource; import java.time.LocalDate; import java.time.LocalTime; import java.util.HashMap; @@ -24,7 +23,7 @@ @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) -class ReservationDAOTest { +class ReservationDaoTest { @Autowired private JdbcTemplate jdbcTemplate; @@ -139,7 +138,7 @@ void should_return_false_when_id_not_exist() { @Test void should_get_reservation_times_when_date_and_theme_given() { LocalDate date = LocalDate.of(2023, 8, 5); - List times = reservationDao.findReservationTimeByDateAndThemeId(date, 1); + List times = reservationDao.findReservationTimeBooked(date, 1); assertThat(times).hasSize(1); assertThat(times).containsExactly(new ReservationTime(1, LocalTime.of(10, 0))); } diff --git a/src/test/java/roomescape/repository/ReservationTimeDAOTest.java b/src/test/java/roomescape/repository/ReservationTimeDaoTest.java similarity index 98% rename from src/test/java/roomescape/repository/ReservationTimeDAOTest.java rename to src/test/java/roomescape/repository/ReservationTimeDaoTest.java index b94ada7fbd..abb82c3c13 100644 --- a/src/test/java/roomescape/repository/ReservationTimeDAOTest.java +++ b/src/test/java/roomescape/repository/ReservationTimeDaoTest.java @@ -11,7 +11,6 @@ import roomescape.model.ReservationTime; import roomescape.repository.dao.ReservationTimeDao; -import javax.sql.DataSource; import java.time.LocalTime; import java.util.HashMap; import java.util.List; @@ -21,7 +20,7 @@ @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) -class ReservationTimeDAOTest { +class ReservationTimeDaoTest { @Autowired private JdbcTemplate jdbcTemplate; diff --git a/src/test/java/roomescape/repository/ThemeDAOTest.java b/src/test/java/roomescape/repository/ThemeDaoTest.java similarity index 99% rename from src/test/java/roomescape/repository/ThemeDAOTest.java rename to src/test/java/roomescape/repository/ThemeDaoTest.java index 1766911adb..2bed2a8117 100644 --- a/src/test/java/roomescape/repository/ThemeDAOTest.java +++ b/src/test/java/roomescape/repository/ThemeDaoTest.java @@ -11,7 +11,6 @@ import roomescape.model.Theme; import roomescape.repository.dao.ThemeDao; -import javax.sql.DataSource; import java.time.LocalDate; import java.time.LocalTime; import java.util.HashMap; @@ -22,7 +21,7 @@ @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) -class ThemeDAOTest { +class ThemeDaoTest { @Autowired private JdbcTemplate jdbcTemplate; diff --git a/src/test/java/roomescape/service/FakeReservationDao.java b/src/test/java/roomescape/service/FakeReservationDao.java index a8f4734c52..8cbd956da4 100644 --- a/src/test/java/roomescape/service/FakeReservationDao.java +++ b/src/test/java/roomescape/service/FakeReservationDao.java @@ -13,6 +13,10 @@ class FakeReservationDao implements ReservationDao { + private List reservationTimes = new ArrayList<>(List.of( + new ReservationTime(1, LocalTime.of(10, 0)), + new ReservationTime(2, LocalTime.of(11, 0)))); + private List reservations = new ArrayList<>(List.of( new Reservation(1, "브라운", LocalDate.of(2030, 8, 5), new ReservationTime(2, LocalTime.of(11, 0)), @@ -64,10 +68,17 @@ public Long countReservationByDateAndTimeId(LocalDate date, long timeId) { } @Override - public List findReservationTimeByDateAndThemeId(LocalDate date, long themeId) { + public List findReservationTimeBooked(LocalDate date, long themeId) { return reservations.stream() .filter(reservation -> reservation.getDate().equals(date) && reservation.getTheme().getThemeId() == themeId) .map(reservation -> new ReservationTime(reservation.getTime().getId(), reservation.getTime().getStartAt())) .toList(); } + + @Override + public List findReservationTimeNotBooked(LocalDate date, long themeId) { + List all = new ArrayList<>(reservationTimes); + all.removeAll(findReservationTimeBooked(date, themeId)); + return all; + } } \ No newline at end of file diff --git a/src/test/java/roomescape/service/ReservationServiceTest.java b/src/test/java/roomescape/service/ReservationServiceTest.java index 7218fe2c21..d3d8e428a4 100644 --- a/src/test/java/roomescape/service/ReservationServiceTest.java +++ b/src/test/java/roomescape/service/ReservationServiceTest.java @@ -105,7 +105,8 @@ void should_throw_exception_when_add_exist_reservation() { @DisplayName("예약 가능 상태를 담은 시간 정보를 반환한다.") @Test void should_return_times_with_book_state() { - List times = reservationService.findReservationTimesInformation(LocalDate.of(2030, 8, 5), 1); + LocalDate date = LocalDate.of(2030, 8, 5); + List times = reservationService.findReservationTimesInformation(date, 1); assertThat(times).hasSize(2); assertThat(times).containsOnly( new MemberReservationTimeResponse(1, LocalTime.of(10, 0), false), From 51e66ef42324ea97282db308baa3eeb66b18e4b1 Mon Sep 17 00:00:00 2001 From: SCY Date: Fri, 3 May 2024 18:52:48 +0900 Subject: [PATCH 47/74] =?UTF-8?q?refactor(MemberReservationTimeResponse):?= =?UTF-8?q?=20=EC=98=88=EC=95=BD=20=EC=83=81=ED=83=9C=20=ED=95=84=EB=93=9C?= =?UTF-8?q?=EB=AA=85=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/ThemeController.java | 2 +- .../MemberReservationTimeResponse.java | 18 +++++++--------- .../response/ReservationResponse.java | 2 +- .../controller/response/ThemeResponse.java | 12 +++++------ src/main/java/roomescape/model/Theme.java | 16 +++++++------- .../repository/dao/JdbcReservationDao.java | 3 +-- .../resources/static/js/user-reservation.js | 4 ++-- .../controller/ThemeControllerTest.java | 21 +++++++++---------- .../service/FakeReservationDao.java | 2 +- .../java/roomescape/service/FakeThemeDao.java | 4 ++-- 10 files changed, 39 insertions(+), 45 deletions(-) diff --git a/src/main/java/roomescape/controller/ThemeController.java b/src/main/java/roomescape/controller/ThemeController.java index 0f2639f17d..f288e474a5 100644 --- a/src/main/java/roomescape/controller/ThemeController.java +++ b/src/main/java/roomescape/controller/ThemeController.java @@ -36,7 +36,7 @@ public ResponseEntity addTheme(@RequestBody ThemeRequest request) Theme theme = themeService.saveTheme(themeDto); ThemeResponse response = ThemeResponse.from(theme); return ResponseEntity - .created(URI.create("/themes/" + response.getId())) + .created(URI.create("/themes/" + response.getThemeId())) .body(response); } diff --git a/src/main/java/roomescape/controller/response/MemberReservationTimeResponse.java b/src/main/java/roomescape/controller/response/MemberReservationTimeResponse.java index 186140b5d0..7a379c097b 100644 --- a/src/main/java/roomescape/controller/response/MemberReservationTimeResponse.java +++ b/src/main/java/roomescape/controller/response/MemberReservationTimeResponse.java @@ -7,16 +7,12 @@ public class MemberReservationTimeResponse { private final long timeId; private final LocalTime startAt; - private boolean alreadyBooked; + private final boolean isBooked; - public MemberReservationTimeResponse(long timeId, LocalTime startAt, boolean alreadyBooked) { + public MemberReservationTimeResponse(long timeId, LocalTime startAt, boolean isBooked) { this.timeId = timeId; this.startAt = startAt; - this.alreadyBooked = alreadyBooked; - } - - public void setAlreadyBooked(boolean alreadyBooked) { - this.alreadyBooked = alreadyBooked; + this.isBooked = isBooked; } public long getTimeId() { @@ -27,8 +23,8 @@ public LocalTime getStartAt() { return startAt; } - public boolean getAlreadyBooked() { - return alreadyBooked; + public boolean getIsBooked() { + return isBooked; } @Override @@ -36,11 +32,11 @@ public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; MemberReservationTimeResponse that = (MemberReservationTimeResponse) o; - return timeId == that.timeId && alreadyBooked == that.alreadyBooked && Objects.equals(startAt, that.startAt); + return timeId == that.timeId && isBooked == that.isBooked && Objects.equals(startAt, that.startAt); } @Override public int hashCode() { - return Objects.hash(timeId, startAt, alreadyBooked); + return Objects.hash(timeId, startAt, isBooked); } } diff --git a/src/main/java/roomescape/controller/response/ReservationResponse.java b/src/main/java/roomescape/controller/response/ReservationResponse.java index 65950c4026..d1ba3bebd2 100644 --- a/src/main/java/roomescape/controller/response/ReservationResponse.java +++ b/src/main/java/roomescape/controller/response/ReservationResponse.java @@ -27,7 +27,7 @@ public static ReservationResponse from(Reservation reservation) { Theme theme = reservation.getTheme(); return new ReservationResponse(reservation.getId(), reservation.getName(), reservation.getDate(), new ReservationTimeResponse(time.getId(), time.getStartAt()), - new ThemeResponse(theme.getThemeId(), theme.getName(), theme.getDescription(), theme.getThumbnail())); + new ThemeResponse(theme.getId(), theme.getName(), theme.getDescription(), theme.getThumbnail())); } public long getId() { diff --git a/src/main/java/roomescape/controller/response/ThemeResponse.java b/src/main/java/roomescape/controller/response/ThemeResponse.java index 4886e40fee..db380ee46b 100644 --- a/src/main/java/roomescape/controller/response/ThemeResponse.java +++ b/src/main/java/roomescape/controller/response/ThemeResponse.java @@ -4,24 +4,24 @@ public class ThemeResponse { - private final long id; + private final long themeId; private final String name; private final String description; private final String thumbnail; - public ThemeResponse(long id, String name, String description, String thumbnail) { - this.id = id; + public ThemeResponse(long themeId, String name, String description, String thumbnail) { + this.themeId = themeId; this.name = name; this.description = description; this.thumbnail = thumbnail; } public static ThemeResponse from(Theme theme) { - return new ThemeResponse(theme.getThemeId(), theme.getName(), theme.getDescription(), theme.getThumbnail()); + return new ThemeResponse(theme.getId(), theme.getName(), theme.getDescription(), theme.getThumbnail()); } - public long getId() { - return id; + public long getThemeId() { + return themeId; } public String getName() { diff --git a/src/main/java/roomescape/model/Theme.java b/src/main/java/roomescape/model/Theme.java index f888e217f0..47e63c19bc 100644 --- a/src/main/java/roomescape/model/Theme.java +++ b/src/main/java/roomescape/model/Theme.java @@ -6,7 +6,7 @@ public class Theme { - private long themeId; + private long id; private String name; private String description; private String thumbnail; @@ -14,8 +14,8 @@ public class Theme { private Theme() { } - public Theme(long themeId, String name, String description, String thumbnail) { - this.themeId = themeId; + public Theme(long id, String name, String description, String thumbnail) { + this.id = id; this.name = name; this.description = description; this.thumbnail = thumbnail; @@ -31,8 +31,8 @@ public static Theme from(ThemeDto themeDto) { return new Theme(themeDto.getName(), themeDto.getDescription(), themeDto.getThumbnail()); } - public long getThemeId() { - return themeId; + public long getId() { + return id; } public String getName() { @@ -52,18 +52,18 @@ public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Theme theme = (Theme) o; - return themeId == theme.themeId && Objects.equals(name, theme.name) && Objects.equals(description, theme.description) && Objects.equals(thumbnail, theme.thumbnail); + return id == theme.id && Objects.equals(name, theme.name) && Objects.equals(description, theme.description) && Objects.equals(thumbnail, theme.thumbnail); } @Override public int hashCode() { - return Objects.hash(themeId, name, description, thumbnail); + return Objects.hash(id, name, description, thumbnail); } @Override public String toString() { return "Theme{" + - "themeId=" + themeId + + "themeId=" + id + ", name='" + name + '\'' + ", description='" + description + '\'' + ", thumbnail='" + thumbnail + '\'' + diff --git a/src/main/java/roomescape/repository/dao/JdbcReservationDao.java b/src/main/java/roomescape/repository/dao/JdbcReservationDao.java index 959be4d5b6..dde4c5f131 100644 --- a/src/main/java/roomescape/repository/dao/JdbcReservationDao.java +++ b/src/main/java/roomescape/repository/dao/JdbcReservationDao.java @@ -7,7 +7,6 @@ import roomescape.model.ReservationTime; import roomescape.model.Theme; -import javax.sql.DataSource; import java.time.LocalDate; import java.util.HashMap; import java.util.List; @@ -68,7 +67,7 @@ public Reservation saveReservation(Reservation reservation) { parameters.put("name", reservation.getName()); parameters.put("date", reservation.getDate()); parameters.put("time_id", reservation.getTime().getId()); - parameters.put("theme_id", reservation.getTheme().getThemeId()); + parameters.put("theme_id", reservation.getTheme().getId()); Number newId = insertActor.executeAndReturnKey(parameters); return new Reservation(newId.longValue(), reservation.getName(), reservation.getDate(), reservation.getTime(), reservation.getTheme()); } diff --git a/src/main/resources/static/js/user-reservation.js b/src/main/resources/static/js/user-reservation.js index b2c5afe5c6..2f55b7b3dd 100644 --- a/src/main/resources/static/js/user-reservation.js +++ b/src/main/resources/static/js/user-reservation.js @@ -122,9 +122,9 @@ function renderAvailableTimes(times) { */ const startAt = time.startAt; const timeId = time.timeId; - const alreadyBooked = time.alreadyBooked; + const isBooked = time.isBooked; - const div = createSlot('time', startAt, timeId, alreadyBooked); // createSlot('time', 시작 시간, time id, 예약 여부) + const div = createSlot('time', startAt, timeId, isBooked); // createSlot('time', 시작 시간, time id, 예약 여부) timeSlots.appendChild(div); }); } diff --git a/src/test/java/roomescape/controller/ThemeControllerTest.java b/src/test/java/roomescape/controller/ThemeControllerTest.java index 8f837edaa6..ff9cbfe565 100644 --- a/src/test/java/roomescape/controller/ThemeControllerTest.java +++ b/src/test/java/roomescape/controller/ThemeControllerTest.java @@ -13,7 +13,6 @@ import roomescape.controller.request.ThemeRequest; import roomescape.controller.response.ThemeResponse; -import javax.sql.DataSource; import java.time.LocalDate; import java.time.LocalTime; import java.util.HashMap; @@ -127,16 +126,16 @@ void should_find_popular_theme() { assertThat(popularThemes).hasSize(10); assertAll(() -> { - assertThat(popularThemes.get(0).getId()).isEqualTo(10); - assertThat(popularThemes.get(1).getId()).isEqualTo(9); - assertThat(popularThemes.get(2).getId()).isEqualTo(1); - assertThat(popularThemes.get(3).getId()).isEqualTo(2); - assertThat(popularThemes.get(4).getId()).isEqualTo(3); - assertThat(popularThemes.get(5).getId()).isEqualTo(4); - assertThat(popularThemes.get(6).getId()).isEqualTo(5); - assertThat(popularThemes.get(7).getId()).isEqualTo(6); - assertThat(popularThemes.get(8).getId()).isEqualTo(7); - assertThat(popularThemes.get(9).getId()).isEqualTo(8); + assertThat(popularThemes.get(0).getThemeId()).isEqualTo(10); + assertThat(popularThemes.get(1).getThemeId()).isEqualTo(9); + assertThat(popularThemes.get(2).getThemeId()).isEqualTo(1); + assertThat(popularThemes.get(3).getThemeId()).isEqualTo(2); + assertThat(popularThemes.get(4).getThemeId()).isEqualTo(3); + assertThat(popularThemes.get(5).getThemeId()).isEqualTo(4); + assertThat(popularThemes.get(6).getThemeId()).isEqualTo(5); + assertThat(popularThemes.get(7).getThemeId()).isEqualTo(6); + assertThat(popularThemes.get(8).getThemeId()).isEqualTo(7); + assertThat(popularThemes.get(9).getThemeId()).isEqualTo(8); }); } diff --git a/src/test/java/roomescape/service/FakeReservationDao.java b/src/test/java/roomescape/service/FakeReservationDao.java index 8cbd956da4..a15b598131 100644 --- a/src/test/java/roomescape/service/FakeReservationDao.java +++ b/src/test/java/roomescape/service/FakeReservationDao.java @@ -70,7 +70,7 @@ public Long countReservationByDateAndTimeId(LocalDate date, long timeId) { @Override public List findReservationTimeBooked(LocalDate date, long themeId) { return reservations.stream() - .filter(reservation -> reservation.getDate().equals(date) && reservation.getTheme().getThemeId() == themeId) + .filter(reservation -> reservation.getDate().equals(date) && reservation.getTheme().getId() == themeId) .map(reservation -> new ReservationTime(reservation.getTime().getId(), reservation.getTime().getStartAt())) .toList(); } diff --git a/src/test/java/roomescape/service/FakeThemeDao.java b/src/test/java/roomescape/service/FakeThemeDao.java index ff3c03137e..ccdbb3d95d 100644 --- a/src/test/java/roomescape/service/FakeThemeDao.java +++ b/src/test/java/roomescape/service/FakeThemeDao.java @@ -34,7 +34,7 @@ public Theme saveTheme(Theme theme) { @Override public void deleteThemeById(long id) { Theme targetTheme = themes.stream() - .filter(theme -> theme.getThemeId() == id) + .filter(theme -> theme.getId() == id) .findFirst() .orElseThrow(() -> new NoSuchElementException("존재하지 않는 테마입니다.")); themes.remove(targetTheme); @@ -43,7 +43,7 @@ public void deleteThemeById(long id) { @Override public Theme findThemeById(long id) { return themes.stream() - .filter(theme -> theme.getThemeId() == id) + .filter(theme -> theme.getId() == id) .findFirst() .orElseThrow(() -> new NoSuchElementException("존재하지 않는 테마입니다.")); } From 82f2fd6cd37522dd77f7f65a26396a09fc1aca0a Mon Sep 17 00:00:00 2001 From: SCY Date: Fri, 3 May 2024 19:24:19 +0900 Subject: [PATCH 48/74] =?UTF-8?q?refactor(dao):=20=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=84=B0=20=EC=A1=B4=EC=9E=AC=20=EC=9C=A0=EB=AC=B4=20=ED=99=95?= =?UTF-8?q?=EC=9D=B8=EC=9D=84=20=EC=9C=84=ED=95=9C=20=EC=BF=BC=EB=A6=AC=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/ReservationRepository.java | 8 ++-- .../repository/ReservationTimeRepository.java | 12 +++--- .../repository/dao/JdbcReservationDao.java | 18 ++++----- .../dao/JdbcReservationTimeDao.java | 15 +++----- .../repository/dao/JdbcThemeDao.java | 1 - .../repository/dao/ReservationDao.java | 6 +-- .../repository/dao/ReservationTimeDao.java | 4 +- .../service/ReservationService.java | 8 ++-- .../service/ReservationTimeService.java | 38 +++++++++++++------ .../repository/ReservationDaoTest.java | 16 ++++---- .../repository/ReservationTimeDaoTest.java | 16 ++++---- .../service/FakeReservationDao.java | 18 +++------ .../service/FakeReservationTimeDao.java | 14 +++---- 13 files changed, 88 insertions(+), 86 deletions(-) diff --git a/src/main/java/roomescape/repository/ReservationRepository.java b/src/main/java/roomescape/repository/ReservationRepository.java index b35bff681a..488579dffe 100644 --- a/src/main/java/roomescape/repository/ReservationRepository.java +++ b/src/main/java/roomescape/repository/ReservationRepository.java @@ -36,16 +36,16 @@ public Theme findThemeById(long id) { return themeDao.findThemeById(id); } - public Long countReservationByDateAndTimeId(LocalDate date, long timeId) { - return reservationDao.countReservationByDateAndTimeId(date, timeId); + public boolean isExistReservationByDateAndTimeId(LocalDate date, long timeId) { + return reservationDao.isExistReservationByDateAndTimeId(date, timeId); } public Reservation saveReservation(Reservation reservation) { return reservationDao.saveReservation(reservation); } - public Long countReservationById(long id) { - return reservationDao.countReservationById(id); + public boolean isExistReservationById(long id) { + return reservationDao.isExistReservationById(id); } public void deleteReservationById(long id) { diff --git a/src/main/java/roomescape/repository/ReservationTimeRepository.java b/src/main/java/roomescape/repository/ReservationTimeRepository.java index d75e67a616..afd64aa5a3 100644 --- a/src/main/java/roomescape/repository/ReservationTimeRepository.java +++ b/src/main/java/roomescape/repository/ReservationTimeRepository.java @@ -23,8 +23,8 @@ public List findAllReservationTimes() { return reservationTimeDao.findAllReservationTimes(); } - public Long countReservationTimeByStartAt(LocalTime startAt) { - return reservationTimeDao.countReservationTimeByStartAt(startAt); + public boolean isExistReservationTimeByStartAt(LocalTime startAt) { + return reservationTimeDao.isExistReservationTimeByStartAt(startAt); } public ReservationTime saveReservationTime(ReservationTime reservationTime) { @@ -35,12 +35,12 @@ public ReservationTime findReservationById(long id) { return reservationTimeDao.findReservationTimeById(id); } - public Long countReservationTimeById(long id) { - return reservationTimeDao.countReservationTimeById(id); + public boolean isExistReservationTimeById(long id) { + return reservationTimeDao.isExistReservationTimeById(id); } - public Long countReservationByTimeId(long timeId) { - return reservationDao.countReservationByTimeId(timeId); + public boolean isExistReservationByTimeId(long timeId) { + return reservationDao.isExistReservationByTimeId(timeId); } public void deleteReservationTimeById(long id) { diff --git a/src/main/java/roomescape/repository/dao/JdbcReservationDao.java b/src/main/java/roomescape/repository/dao/JdbcReservationDao.java index dde4c5f131..c65269441a 100644 --- a/src/main/java/roomescape/repository/dao/JdbcReservationDao.java +++ b/src/main/java/roomescape/repository/dao/JdbcReservationDao.java @@ -79,21 +79,21 @@ public void deleteReservationById(long id) { } @Override - public Long countReservationById(long id) { - String sql = "select count(id) from reservation where id = ?"; - return jdbcTemplate.queryForObject(sql, (resultSet, ignored) -> resultSet.getLong(1), id); + public boolean isExistReservationById(long id) { + String sql = "select exists (select id from reservation where id = ?)"; + return jdbcTemplate.queryForObject(sql, Boolean.class, id); } @Override - public Long countReservationByTimeId(long timeId) { - String sql = "select count(id) from reservation where time_id = ?"; - return jdbcTemplate.queryForObject(sql, (resultSet, ignored) -> resultSet.getLong(1), timeId); + public boolean isExistReservationByTimeId(long timeId) { + String sql = "select exists (select id from reservation where time_id = ?)"; + return jdbcTemplate.queryForObject(sql, Boolean.class, timeId); } @Override - public Long countReservationByDateAndTimeId(LocalDate date, long timeId) { - String sql = "select count(id) from reservation where date = ? and time_id = ?"; - return jdbcTemplate.queryForObject(sql, (resultSet, ignored) -> resultSet.getLong(1), date, timeId); + public boolean isExistReservationByDateAndTimeId(LocalDate date, long timeId) { + String sql = "select exists (select id from reservation where date = ? and time_id = ?)"; + return jdbcTemplate.queryForObject(sql, Boolean.class, date, timeId); } @Override diff --git a/src/main/java/roomescape/repository/dao/JdbcReservationTimeDao.java b/src/main/java/roomescape/repository/dao/JdbcReservationTimeDao.java index b6f38f967b..5405854dc3 100644 --- a/src/main/java/roomescape/repository/dao/JdbcReservationTimeDao.java +++ b/src/main/java/roomescape/repository/dao/JdbcReservationTimeDao.java @@ -5,7 +5,6 @@ import org.springframework.stereotype.Repository; import roomescape.model.ReservationTime; -import javax.sql.DataSource; import java.time.LocalTime; import java.util.HashMap; import java.util.List; @@ -60,16 +59,14 @@ public void deleteReservationTimeById(long id) { } @Override - public Long countReservationTimeById(long id) { - String sql = "select count(id) from reservation_time where id = ?"; - return jdbcTemplate.queryForObject(sql, (resultSet, ignored) -> - resultSet.getLong(1), id); + public boolean isExistReservationTimeById(long id) { + String sql = "select exists(select id from reservation_time where id = ?)"; + return jdbcTemplate.queryForObject(sql, Boolean.class, id); } @Override - public Long countReservationTimeByStartAt(LocalTime startAt) { - String sql = "select count(id) from reservation_time where start_at = ?"; - return jdbcTemplate.queryForObject(sql, (resultSet, ignored) -> - resultSet.getLong(1), startAt); + public boolean isExistReservationTimeByStartAt(LocalTime startAt) { + String sql = "select exists (select id from reservation_time where start_at = ?)"; + return jdbcTemplate.queryForObject(sql, Boolean.class, startAt); } } diff --git a/src/main/java/roomescape/repository/dao/JdbcThemeDao.java b/src/main/java/roomescape/repository/dao/JdbcThemeDao.java index e030a8ad79..fd7d0c4c39 100644 --- a/src/main/java/roomescape/repository/dao/JdbcThemeDao.java +++ b/src/main/java/roomescape/repository/dao/JdbcThemeDao.java @@ -5,7 +5,6 @@ import org.springframework.stereotype.Repository; import roomescape.model.Theme; -import javax.sql.DataSource; import java.time.LocalDate; import java.util.HashMap; import java.util.List; diff --git a/src/main/java/roomescape/repository/dao/ReservationDao.java b/src/main/java/roomescape/repository/dao/ReservationDao.java index 4b043d1f16..a848ff793d 100644 --- a/src/main/java/roomescape/repository/dao/ReservationDao.java +++ b/src/main/java/roomescape/repository/dao/ReservationDao.java @@ -14,11 +14,11 @@ public interface ReservationDao { void deleteReservationById(long id); - Long countReservationById(long id); + boolean isExistReservationById(long id); - Long countReservationByTimeId(long timeId); + boolean isExistReservationByTimeId(long timeId); - Long countReservationByDateAndTimeId(LocalDate date, long timeId); + boolean isExistReservationByDateAndTimeId(LocalDate date, long timeId); List findReservationTimeBooked(LocalDate date, long themeId); diff --git a/src/main/java/roomescape/repository/dao/ReservationTimeDao.java b/src/main/java/roomescape/repository/dao/ReservationTimeDao.java index 426ea5c301..15d835fea4 100644 --- a/src/main/java/roomescape/repository/dao/ReservationTimeDao.java +++ b/src/main/java/roomescape/repository/dao/ReservationTimeDao.java @@ -15,7 +15,7 @@ public interface ReservationTimeDao { void deleteReservationTimeById(long id); - Long countReservationTimeById(long id); + boolean isExistReservationTimeById(long id); - Long countReservationTimeByStartAt(LocalTime startAt); + boolean isExistReservationTimeByStartAt(LocalTime startAt); } diff --git a/src/main/java/roomescape/service/ReservationService.java b/src/main/java/roomescape/service/ReservationService.java index 2a88a8361a..3ae3aaf2da 100644 --- a/src/main/java/roomescape/service/ReservationService.java +++ b/src/main/java/roomescape/service/ReservationService.java @@ -57,8 +57,8 @@ private void validateDateTime(LocalDate date, ReservationTime time) { } private void validateDuplication(LocalDate date, long timeId) { - Long countReservation = reservationRepository.countReservationByDateAndTimeId(date, timeId); - if (countReservation == null || countReservation > 0) { + boolean isExist = reservationRepository.isExistReservationByDateAndTimeId(date, timeId); + if (isExist) { throw new DuplicatedException("[ERROR] 중복되는 예약은 추가할 수 없습니다."); } } @@ -69,8 +69,8 @@ public void deleteReservation(long id) { } private void validateExistence(long id) { - Long count = reservationRepository.countReservationById(id); - if (count == null || count <= 0) { + boolean isNotExist = !reservationRepository.isExistReservationById(id); + if (isNotExist) { throw new NotFoundException("[ERROR] 존재하지 않는 예약입니다."); } } diff --git a/src/main/java/roomescape/service/ReservationTimeService.java b/src/main/java/roomescape/service/ReservationTimeService.java index e012a603b8..1514a3ff48 100644 --- a/src/main/java/roomescape/service/ReservationTimeService.java +++ b/src/main/java/roomescape/service/ReservationTimeService.java @@ -26,27 +26,43 @@ public List findAllReservationTimes() { public ReservationTime saveReservationTime(ReservationTimeDto reservationTimeDto) { LocalTime startAt = reservationTimeDto.getStartAt(); - Long countReservationTimeByStartAt = reservationTimeRepository.countReservationTimeByStartAt(startAt); - if (countReservationTimeByStartAt == null || countReservationTimeByStartAt > 0) { - throw new DuplicatedException("[ERROR] 중복되는 시간은 추가할 수 없습니다."); - } + validateDuplication(startAt); ReservationTime reservationTime = new ReservationTime(reservationTimeDto.getStartAt()); return reservationTimeRepository.saveReservationTime(reservationTime); } + private void validateDuplication(LocalTime startAt) { + boolean isExist = reservationTimeRepository.isExistReservationTimeByStartAt(startAt); + if (isExist) { + throw new DuplicatedException("[ERROR] 중복되는 시간은 추가할 수 없습니다."); + } + } + public ReservationTime findReservationTime(long id) { return reservationTimeRepository.findReservationById(id); } public void deleteReservationTime(long id) { - Long count = reservationTimeRepository.countReservationTimeById(id); - if (count == null || count <= 0) { - throw new NotFoundException("[ERROR] 존재하지 않는 시간입니다."); - } - Long countOfReservationUsingTime = reservationTimeRepository.countReservationByTimeId(id); - if (countOfReservationUsingTime == null || countOfReservationUsingTime > 0) { + validate(id); + reservationTimeRepository.deleteReservationTimeById(id); + } + + private void validate(long id) { + validateExistence(id); + validateDependence(id); + } + + private void validateDependence(long id) { + boolean isExist = reservationTimeRepository.isExistReservationByTimeId(id); + if (isExist) { throw new BadRequestException("[ERROR] 해당 시간을 사용하고 있는 예약이 있습니다."); } - reservationTimeRepository.deleteReservationTimeById(id); + } + + private void validateExistence(long id) { + boolean isNotExist = !reservationTimeRepository.isExistReservationTimeById(id); + if (isNotExist) { + throw new NotFoundException("[ERROR] 존재하지 않는 시간입니다."); + } } } diff --git a/src/test/java/roomescape/repository/ReservationDaoTest.java b/src/test/java/roomescape/repository/ReservationDaoTest.java index cb003d8b15..d3a38be070 100644 --- a/src/test/java/roomescape/repository/ReservationDaoTest.java +++ b/src/test/java/roomescape/repository/ReservationDaoTest.java @@ -120,18 +120,18 @@ void should_delete_reservation() { assertThat(count).isEqualTo(1); } - @DisplayName("아이디가 존재하면 참을 반환한다.") + @DisplayName("특정 id를 가진 데이터가 존재하면 참을 반환한다.") @Test - void should_return_true_when_id_exist() { - long count = reservationDao.countReservationById(1); - assertThat(count).isEqualTo(1); + void should_return_true_when_exist() { + boolean isExist = reservationDao.isExistReservationById(1); + assertThat(isExist).isTrue(); } - @DisplayName("아이디가 존재하면 거짓을 반환한다.") + @DisplayName("특정 id를 가진 데이터가 존재하지 않으면 거짓을 반환한다.") @Test - void should_return_false_when_id_not_exist() { - long count = reservationDao.countReservationById(100000000); - assertThat(count).isEqualTo(0); + void should_return_false_when_not_exist() { + boolean isExist = reservationDao.isExistReservationById(100000000); + assertThat(isExist).isFalse(); } @DisplayName("특정 날짜와 테마에 해당하는 시간을 조회한다.") diff --git a/src/test/java/roomescape/repository/ReservationTimeDaoTest.java b/src/test/java/roomescape/repository/ReservationTimeDaoTest.java index abb82c3c13..7886b0ac62 100644 --- a/src/test/java/roomescape/repository/ReservationTimeDaoTest.java +++ b/src/test/java/roomescape/repository/ReservationTimeDaoTest.java @@ -79,17 +79,17 @@ void should_get_reservation_time() { assertThat(reservationTime.getStartAt()).isEqualTo(LocalTime.of(10, 0)); } - @DisplayName("아이디가 존재하면 참을 반환한다.") + @DisplayName("특정 id를 갖는 데이터가 존재하는 경우 참을 반환한다.") @Test - void should_return_true_when_id_exist() { - long count = reservationTimeDao.countReservationTimeById(1); - assertThat(count).isEqualTo(1); + void should_return_true_when_exist() { + Boolean isExist = reservationTimeDao.isExistReservationTimeById(1); + assertThat(isExist).isTrue(); } - @DisplayName("아이디가 존재하면 거짓을 반환한다.") + @DisplayName("특정 id를 갖는 데이터가 존재하지 않는 경우 거짓을 반환한다.") @Test - void should_return_false_when_id_not_exist() { - long count = reservationTimeDao.countReservationTimeById(100000000); - assertThat(count).isEqualTo(0); + void should_return_false_when_not_exist() { + Boolean isExist = reservationTimeDao.isExistReservationTimeById(100000000); + assertThat(isExist).isFalse(); } } diff --git a/src/test/java/roomescape/service/FakeReservationDao.java b/src/test/java/roomescape/service/FakeReservationDao.java index a15b598131..020058829c 100644 --- a/src/test/java/roomescape/service/FakeReservationDao.java +++ b/src/test/java/roomescape/service/FakeReservationDao.java @@ -46,25 +46,19 @@ public void deleteReservationById(long id) { } @Override - public Long countReservationById(long id) { - return reservations.stream() - .filter(reservation -> reservation.getId() == id) - .count(); + public boolean isExistReservationById(long id) { + return reservations.stream().anyMatch(reservation -> reservation.getId() == id); } @Override - public Long countReservationByTimeId(long timeId) { - return reservations.stream() - .filter(reservation -> reservation.getTime().getId() == timeId) - .count(); + public boolean isExistReservationByTimeId(long timeId) { + return reservations.stream().anyMatch(reservation -> reservation.getTime().getId() == timeId); } @Override - public Long countReservationByDateAndTimeId(LocalDate date, long timeId) { + public boolean isExistReservationByDateAndTimeId(LocalDate date, long timeId) { return reservations.stream() - .filter(reservation -> reservation.getDate().isEqual(date) - && reservation.getTime().getId() == timeId) - .count(); + .anyMatch(reservation -> reservation.getDate().isEqual(date) && reservation.getTime().getId() == timeId); } @Override diff --git a/src/test/java/roomescape/service/FakeReservationTimeDao.java b/src/test/java/roomescape/service/FakeReservationTimeDao.java index b39683b9ad..79381d923a 100644 --- a/src/test/java/roomescape/service/FakeReservationTimeDao.java +++ b/src/test/java/roomescape/service/FakeReservationTimeDao.java @@ -10,7 +10,7 @@ class FakeReservationTimeDao implements ReservationTimeDao { - private List reservationTimes = new ArrayList<>(List.of( + private final List reservationTimes = new ArrayList<>(List.of( new ReservationTime(1, LocalTime.of(10, 0)), new ReservationTime(2, LocalTime.of(11, 0)) )); @@ -49,16 +49,12 @@ public void deleteReservationTimeById(long id) { } @Override - public Long countReservationTimeById(long id) { - return reservationTimes.stream() - .filter(reservationTime -> reservationTime.getId() == id) - .count(); + public boolean isExistReservationTimeById(long id) { + return reservationTimes.stream().anyMatch(reservationTime -> reservationTime.getId() == id); } @Override - public Long countReservationTimeByStartAt(LocalTime startAt) { - return reservationTimes.stream() - .filter(reservationTime -> reservationTime.getStartAt() == startAt) - .count(); + public boolean isExistReservationTimeByStartAt(LocalTime startAt) { + return reservationTimes.stream().anyMatch(reservationTime -> reservationTime.getStartAt() == startAt); } } From 277a0b8da6f1c4980b0429aa344caa3cfd9e4780 Mon Sep 17 00:00:00 2001 From: SCY Date: Fri, 3 May 2024 19:38:16 +0900 Subject: [PATCH 49/74] =?UTF-8?q?refactor(ThemeService):=20=EB=A7=A4?= =?UTF-8?q?=EC=A7=81=EB=84=98=EB=B2=84=20=EC=83=81=EC=88=98=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/roomescape/repository/ThemeRepository.java | 4 ++-- src/main/java/roomescape/service/ThemeService.java | 9 ++++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/main/java/roomescape/repository/ThemeRepository.java b/src/main/java/roomescape/repository/ThemeRepository.java index 3070cc2491..2f3624e80e 100644 --- a/src/main/java/roomescape/repository/ThemeRepository.java +++ b/src/main/java/roomescape/repository/ThemeRepository.java @@ -28,7 +28,7 @@ public void deleteThemeById(long id) { themeDao.deleteThemeById(id); } - public List findThemeRankingByDate(LocalDate before, LocalDate after, int i) { - return themeDao.findThemeRankingByDate(before, after, 10); + public List findThemeRankingByDate(LocalDate before, LocalDate after, int rankingCount) { + return themeDao.findThemeRankingByDate(before, after, rankingCount); } } diff --git a/src/main/java/roomescape/service/ThemeService.java b/src/main/java/roomescape/service/ThemeService.java index 27a8228059..56adfb62a5 100644 --- a/src/main/java/roomescape/service/ThemeService.java +++ b/src/main/java/roomescape/service/ThemeService.java @@ -11,6 +11,9 @@ @Service public class ThemeService { + private static final int COUNT_OF_DAY = 7; + private static final int COUNT_OF_RANKING = 10; + private final ThemeRepository themeRepository; public ThemeService(ThemeRepository themeRepository) { @@ -31,8 +34,8 @@ public void deleteTheme(long id) { } public List findPopularThemes() { - LocalDate before = LocalDate.now().minusDays(8); - LocalDate after = LocalDate.now().minusDays(1); - return themeRepository.findThemeRankingByDate(before, after, 10); + LocalDate startDate = LocalDate.now().minusDays(1 + COUNT_OF_DAY); + LocalDate endDate = LocalDate.now().minusDays(1); + return themeRepository.findThemeRankingByDate(startDate, endDate, COUNT_OF_RANKING); } } From 4274210799a1c32d4de686d21e3c07952c344048 Mon Sep 17 00:00:00 2001 From: SCY Date: Sun, 5 May 2024 18:00:42 +0900 Subject: [PATCH 50/74] =?UTF-8?q?refactor(dao):=20sql=20join=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/ThemeController.java | 2 +- .../controller/response/ThemeResponse.java | 10 +- .../repository/ReservationRepository.java | 49 ++++-- .../repository/ReservationTimeRepository.java | 20 +-- .../repository/ThemeRepository.java | 27 +++- .../repository/dao/JdbcReservationDao.java | 137 ++++++++--------- .../dao/JdbcReservationTimeDao.java | 32 ++-- .../repository/dao/JdbcThemeDao.java | 54 +++---- .../repository/dao/ReservationDao.java | 21 +-- .../repository/dao/ReservationTimeDao.java | 13 +- .../roomescape/repository/dao/ThemeDao.java | 12 +- .../repository/dto/ReservationSavedDto.java | 54 +++++++ .../service/ReservationService.java | 6 +- .../service/ReservationTimeService.java | 6 +- .../java/roomescape/service/ThemeService.java | 4 +- .../controller/ThemeControllerTest.java | 20 +-- .../repository/ReservationDaoTest.java | 23 +-- .../repository/ReservationTimeDaoTest.java | 12 +- .../roomescape/repository/ThemeDaoTest.java | 16 +- .../service/FakeReservationDao.java | 144 +++++++++++++----- .../service/FakeReservationTimeDao.java | 41 +++-- .../java/roomescape/service/FakeThemeDao.java | 46 ++---- .../service/ReservationServiceTest.java | 36 +++-- .../service/ReservationTimeServiceTest.java | 22 ++- .../roomescape/service/ThemeServiceTest.java | 37 +++-- 25 files changed, 499 insertions(+), 345 deletions(-) create mode 100644 src/main/java/roomescape/repository/dto/ReservationSavedDto.java diff --git a/src/main/java/roomescape/controller/ThemeController.java b/src/main/java/roomescape/controller/ThemeController.java index f288e474a5..0f2639f17d 100644 --- a/src/main/java/roomescape/controller/ThemeController.java +++ b/src/main/java/roomescape/controller/ThemeController.java @@ -36,7 +36,7 @@ public ResponseEntity addTheme(@RequestBody ThemeRequest request) Theme theme = themeService.saveTheme(themeDto); ThemeResponse response = ThemeResponse.from(theme); return ResponseEntity - .created(URI.create("/themes/" + response.getThemeId())) + .created(URI.create("/themes/" + response.getId())) .body(response); } diff --git a/src/main/java/roomescape/controller/response/ThemeResponse.java b/src/main/java/roomescape/controller/response/ThemeResponse.java index db380ee46b..4ef8a74b54 100644 --- a/src/main/java/roomescape/controller/response/ThemeResponse.java +++ b/src/main/java/roomescape/controller/response/ThemeResponse.java @@ -4,13 +4,13 @@ public class ThemeResponse { - private final long themeId; + private final long id; private final String name; private final String description; private final String thumbnail; - public ThemeResponse(long themeId, String name, String description, String thumbnail) { - this.themeId = themeId; + public ThemeResponse(long id, String name, String description, String thumbnail) { + this.id = id; this.name = name; this.description = description; this.thumbnail = thumbnail; @@ -20,8 +20,8 @@ public static ThemeResponse from(Theme theme) { return new ThemeResponse(theme.getId(), theme.getName(), theme.getDescription(), theme.getThumbnail()); } - public long getThemeId() { - return themeId; + public long getId() { + return id; } public String getName() { diff --git a/src/main/java/roomescape/repository/ReservationRepository.java b/src/main/java/roomescape/repository/ReservationRepository.java index 488579dffe..219328d762 100644 --- a/src/main/java/roomescape/repository/ReservationRepository.java +++ b/src/main/java/roomescape/repository/ReservationRepository.java @@ -7,9 +7,11 @@ import roomescape.repository.dao.ReservationDao; import roomescape.repository.dao.ReservationTimeDao; import roomescape.repository.dao.ThemeDao; +import roomescape.repository.dto.ReservationSavedDto; import java.time.LocalDate; -import java.util.List; +import java.util.*; +import java.util.stream.Collectors; @Repository public class ReservationRepository { @@ -25,38 +27,61 @@ public ReservationRepository(ReservationDao reservationDao, ReservationTimeDao r } public List findAllReservations() { - return reservationDao.findAllReservations(); + List result = new ArrayList<>(); + List reservations = reservationDao.findAll(); + for (ReservationSavedDto reservation : reservations) { + ReservationTime time = reservationTimeDao.findById(reservation.getTimeId()).orElseThrow(NoSuchElementException::new); + Theme theme = themeDao.findById(reservation.getThemeId()).orElseThrow(NoSuchElementException::new); + result.add(new Reservation(reservation.getId(), reservation.getName(), reservation.getDate(), time, theme)); + } + return result; } - public ReservationTime findReservationTimeById(long id) { - return reservationTimeDao.findReservationTimeById(id); + public Optional findReservationTimeById(long id) { + return reservationTimeDao.findById(id); } - public Theme findThemeById(long id) { - return themeDao.findThemeById(id); + public Optional findThemeById(long id) { + return themeDao.findById(id); } public boolean isExistReservationByDateAndTimeId(LocalDate date, long timeId) { - return reservationDao.isExistReservationByDateAndTimeId(date, timeId); + return reservationDao.isExistByDateAndTimeId(date, timeId); } public Reservation saveReservation(Reservation reservation) { - return reservationDao.saveReservation(reservation); + long id = reservationDao.save(reservation); + ReservationSavedDto saved = reservationDao.findById(id).orElseThrow(NoSuchElementException::new); + ReservationTime time = reservationTimeDao.findById(saved.getTimeId()).orElseThrow(NoSuchElementException::new); + Theme theme = themeDao.findById(saved.getThemeId()).orElseThrow(NoSuchElementException::new); + return new Reservation(id, saved.getName(), saved.getDate(), time, theme); } public boolean isExistReservationById(long id) { - return reservationDao.isExistReservationById(id); + return reservationDao.isExistById(id); } public void deleteReservationById(long id) { - reservationDao.deleteReservationById(id); + reservationDao.deleteById(id); } public List findReservationTimeBooked(LocalDate date, long themeId) { - return reservationDao.findReservationTimeBooked(date, themeId); + List result = new ArrayList<>(); + List reservations = reservationDao.findByDateAndThemeId(date, themeId); + Set timeIds = reservations.stream() + .map(ReservationSavedDto::getTimeId) + .collect(Collectors.toSet()); + for (long timeId : timeIds) { + ReservationTime time = reservationTimeDao.findById(timeId).orElseThrow(NoSuchElementException::new); + result.add(time); + } + return result; } public List findReservationTimeNotBooked(LocalDate date, long themeId) { - return reservationDao.findReservationTimeNotBooked(date, themeId); + List result = reservationTimeDao.findAll(); + List bookedTimes = findReservationTimeBooked(date, themeId); + result.removeAll(bookedTimes); + return result; } } diff --git a/src/main/java/roomescape/repository/ReservationTimeRepository.java b/src/main/java/roomescape/repository/ReservationTimeRepository.java index afd64aa5a3..70218abb1f 100644 --- a/src/main/java/roomescape/repository/ReservationTimeRepository.java +++ b/src/main/java/roomescape/repository/ReservationTimeRepository.java @@ -7,6 +7,7 @@ import java.time.LocalTime; import java.util.List; +import java.util.Optional; @Repository public class ReservationTimeRepository { @@ -20,30 +21,31 @@ public ReservationTimeRepository(ReservationDao reservationDao, ReservationTimeD } public List findAllReservationTimes() { - return reservationTimeDao.findAllReservationTimes(); + return reservationTimeDao.findAll(); } public boolean isExistReservationTimeByStartAt(LocalTime startAt) { - return reservationTimeDao.isExistReservationTimeByStartAt(startAt); + return reservationTimeDao.isExistByStartAt(startAt); } - public ReservationTime saveReservationTime(ReservationTime reservationTime) { - return reservationTimeDao.saveReservationTime(reservationTime); + public Optional saveReservationTime(ReservationTime reservationTime) { + long id = reservationTimeDao.save(reservationTime); + return reservationTimeDao.findById(id); } - public ReservationTime findReservationById(long id) { - return reservationTimeDao.findReservationTimeById(id); + public Optional findReservationById(long id) { + return reservationTimeDao.findById(id); } public boolean isExistReservationTimeById(long id) { - return reservationTimeDao.isExistReservationTimeById(id); + return reservationTimeDao.isExistById(id); } public boolean isExistReservationByTimeId(long timeId) { - return reservationDao.isExistReservationByTimeId(timeId); + return reservationDao.isExistByTimeId(timeId); } public void deleteReservationTimeById(long id) { - reservationTimeDao.deleteReservationTimeById(id); + reservationTimeDao.deleteById(id); } } diff --git a/src/main/java/roomescape/repository/ThemeRepository.java b/src/main/java/roomescape/repository/ThemeRepository.java index 2f3624e80e..e4f5e6097a 100644 --- a/src/main/java/roomescape/repository/ThemeRepository.java +++ b/src/main/java/roomescape/repository/ThemeRepository.java @@ -2,33 +2,46 @@ import org.springframework.stereotype.Repository; import roomescape.model.Theme; +import roomescape.repository.dao.ReservationDao; import roomescape.repository.dao.ThemeDao; import java.time.LocalDate; +import java.util.ArrayList; import java.util.List; +import java.util.NoSuchElementException; +import java.util.Optional; @Repository public class ThemeRepository { + private final ReservationDao reservationDao; private final ThemeDao themeDao; - public ThemeRepository(ThemeDao themeDao) { + public ThemeRepository(ReservationDao reservationDao, ThemeDao themeDao) { + this.reservationDao = reservationDao; this.themeDao = themeDao; } public List findAllThemes() { - return themeDao.findAllThemes(); + return themeDao.findAll(); } - public Theme saveTheme(Theme theme) { - return themeDao.saveTheme(theme); + public Optional saveTheme(Theme theme) { + long id = themeDao.save(theme); + return themeDao.findById(id); } public void deleteThemeById(long id) { - themeDao.deleteThemeById(id); + themeDao.deleteById(id); } - public List findThemeRankingByDate(LocalDate before, LocalDate after, int rankingCount) { - return themeDao.findThemeRankingByDate(before, after, rankingCount); + public List findThemeRankingByDate(LocalDate startDate, LocalDate endDate, int rankingCount) { + List result = new ArrayList<>(); + List themeIds = reservationDao.findByDateAndGroupByThemeIdAndOrderByCountAndLimit(startDate, endDate, rankingCount); + for (long themeId : themeIds) { + Theme theme = themeDao.findById(themeId).orElseThrow(NoSuchElementException::new); + result.add(theme); + } + return result; } } diff --git a/src/main/java/roomescape/repository/dao/JdbcReservationDao.java b/src/main/java/roomescape/repository/dao/JdbcReservationDao.java index c65269441a..63af2bd354 100644 --- a/src/main/java/roomescape/repository/dao/JdbcReservationDao.java +++ b/src/main/java/roomescape/repository/dao/JdbcReservationDao.java @@ -4,19 +4,18 @@ import org.springframework.jdbc.core.simple.SimpleJdbcInsert; import org.springframework.stereotype.Repository; import roomescape.model.Reservation; -import roomescape.model.ReservationTime; -import roomescape.model.Theme; +import roomescape.repository.dto.ReservationSavedDto; import java.time.LocalDate; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; @Repository public class JdbcReservationDao implements ReservationDao { private final JdbcTemplate jdbcTemplate; - private final SimpleJdbcInsert insertActor; public JdbcReservationDao(JdbcTemplate jdbcTemplate) { @@ -27,103 +26,87 @@ public JdbcReservationDao(JdbcTemplate jdbcTemplate) { } @Override - public List findAllReservations() { - String sql = """ - select - r.id as reservation_id, - r.name, - r.date, - t.id as time_id, - t.start_at as time_start_at, - th.id as theme_id, - th.name as theme_name, - th.description, - th.thumbnail - from reservation as r - inner join reservation_time as t on r.time_id = t.id - inner join theme as th on r.theme_id = th.id - """; - return jdbcTemplate.query(sql, (resultSet, rowNum) -> - new Reservation( - resultSet.getLong("reservation_id"), - resultSet.getString("name"), - resultSet.getDate("date").toLocalDate(), - new ReservationTime( - resultSet.getLong("time_id"), - resultSet.getTime("time_start_at").toLocalTime() - ), - new Theme( - resultSet.getLong("theme_id"), - resultSet.getString("theme_name"), - resultSet.getString("description"), - resultSet.getString("thumbnail") - ) - )); - } - - @Override - public Reservation saveReservation(Reservation reservation) { - Map parameters = new HashMap<>(3); + public long save(Reservation reservation) { + Map parameters = new HashMap<>(4); parameters.put("name", reservation.getName()); parameters.put("date", reservation.getDate()); parameters.put("time_id", reservation.getTime().getId()); parameters.put("theme_id", reservation.getTheme().getId()); - Number newId = insertActor.executeAndReturnKey(parameters); - return new Reservation(newId.longValue(), reservation.getName(), reservation.getDate(), reservation.getTime(), reservation.getTheme()); + return insertActor.executeAndReturnKey(parameters).longValue(); + } + + @Override + public List findAll() { + String sql2 = "select id, name, date, time_id, theme_id from reservation"; + return jdbcTemplate.query(sql2, (resultSet, rowNum) -> new ReservationSavedDto( + resultSet.getLong("id"), + resultSet.getString("name"), + resultSet.getDate("date").toLocalDate(), + resultSet.getLong("time_id"), + resultSet.getLong("theme_id") + )); } @Override - public void deleteReservationById(long id) { + public Optional findById(long id) { + String sql2 = "select id, name, date, time_id, theme_id from reservation where id = ?"; + ReservationSavedDto reservation = jdbcTemplate.queryForObject(sql2, (resultSet, rowNum) -> new ReservationSavedDto( + resultSet.getLong("id"), + resultSet.getString("name"), + resultSet.getDate("date").toLocalDate(), + resultSet.getLong("time_id"), + resultSet.getLong("theme_id") + ), id); + return Optional.ofNullable(reservation); + } + + @Override + public List findByDateAndThemeId(LocalDate date, long themeId) { + String sql = "select id, name, date, time_id, theme_id from reservation where date = ? and theme_id = ?"; + return jdbcTemplate.query(sql, (resultSet, rowNum) -> new ReservationSavedDto( + resultSet.getLong("id"), + resultSet.getString("name"), + resultSet.getDate("date").toLocalDate(), + resultSet.getLong("time_id"), + resultSet.getLong("theme_id") + ), date, themeId); + } + + @Override + public List findByDateAndGroupByThemeIdAndOrderByCountAndLimit(LocalDate startDate, LocalDate endDate, int limit) { + String sql = """ + select theme_id + from reservation + where date between ? and ? + group by theme_id + order by count(theme_id) desc + limit ? + """; + return jdbcTemplate.query(sql, (resultSet, rowNum) -> resultSet.getLong("theme_id"), + startDate, endDate, limit); + } + + @Override + public void deleteById(long id) { String sql = "delete from reservation where id = ?"; jdbcTemplate.update(sql, id); } @Override - public boolean isExistReservationById(long id) { + public Boolean isExistById(long id) { String sql = "select exists (select id from reservation where id = ?)"; return jdbcTemplate.queryForObject(sql, Boolean.class, id); } @Override - public boolean isExistReservationByTimeId(long timeId) { + public Boolean isExistByTimeId(long timeId) { String sql = "select exists (select id from reservation where time_id = ?)"; return jdbcTemplate.queryForObject(sql, Boolean.class, timeId); } @Override - public boolean isExistReservationByDateAndTimeId(LocalDate date, long timeId) { + public Boolean isExistByDateAndTimeId(LocalDate date, long timeId) { String sql = "select exists (select id from reservation where date = ? and time_id = ?)"; return jdbcTemplate.queryForObject(sql, Boolean.class, date, timeId); } - - @Override - public List findReservationTimeNotBooked(LocalDate date, long themeId) { - String sql = """ - select t.id as time_id, t.start_at as start_at - from reservation_time as t - minus - select t.id as time_id, t.start_at as start_at - from reservation as r inner join reservation_time as t on r.time_id = t.id - where date = ? and theme_id = ? - """; - return jdbcTemplate.query(sql, (resultSet, rowNum) -> - new ReservationTime( - resultSet.getLong("time_id"), - resultSet.getTime("start_at").toLocalTime() - ), date, themeId); - } - - @Override - public List findReservationTimeBooked(LocalDate date, long themeId) { - String sql = """ - select t.id as time_id, t.start_at as start_at - from reservation as r inner join reservation_time as t on r.time_id = t.id - where date = ? and theme_id = ? - """; - return jdbcTemplate.query(sql, (resultSet, rowNum) -> - new ReservationTime( - resultSet.getLong("time_id"), - resultSet.getTime("start_at").toLocalTime() - ), date, themeId); - } } diff --git a/src/main/java/roomescape/repository/dao/JdbcReservationTimeDao.java b/src/main/java/roomescape/repository/dao/JdbcReservationTimeDao.java index 5405854dc3..5e11a65649 100644 --- a/src/main/java/roomescape/repository/dao/JdbcReservationTimeDao.java +++ b/src/main/java/roomescape/repository/dao/JdbcReservationTimeDao.java @@ -9,12 +9,12 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; @Repository public class JdbcReservationTimeDao implements ReservationTimeDao { private final JdbcTemplate jdbcTemplate; - private final SimpleJdbcInsert insertActor; public JdbcReservationTimeDao(JdbcTemplate jdbcTemplate) { @@ -25,7 +25,14 @@ public JdbcReservationTimeDao(JdbcTemplate jdbcTemplate) { } @Override - public List findAllReservationTimes() { + public long save(ReservationTime reservationTime) { + Map parameters = new HashMap<>(1); + parameters.put("start_at", reservationTime.getStartAt()); + return insertActor.executeAndReturnKey(parameters).longValue(); + } + + @Override + public List findAll() { String sql = "select id, start_at from reservation_time"; return jdbcTemplate.query(sql, (resultSet, rowNum) -> new ReservationTime( @@ -35,37 +42,30 @@ public List findAllReservationTimes() { } @Override - public ReservationTime findReservationTimeById(long id) { - String sql = "select * from reservation_time where id = ?"; - return jdbcTemplate.queryForObject(sql, (resultSet, rowNum) -> + public Optional findById(long id) { + String sql = "select id, start_at from reservation_time where id = ?"; + ReservationTime reservationTime = jdbcTemplate.queryForObject(sql, (resultSet, rowNum) -> new ReservationTime( resultSet.getLong("id"), resultSet.getTime("start_at").toLocalTime() ), id); + return Optional.ofNullable(reservationTime); } @Override - public ReservationTime saveReservationTime(ReservationTime reservationTime) { - Map parameters = new HashMap<>(1); - parameters.put("start_at", reservationTime.getStartAt()); - Number newId = insertActor.executeAndReturnKey(parameters); - return new ReservationTime(newId.longValue(), reservationTime.getStartAt()); - } - - @Override - public void deleteReservationTimeById(long id) { + public void deleteById(long id) { String sql = "delete from reservation_time where id = ?"; jdbcTemplate.update(sql, id); } @Override - public boolean isExistReservationTimeById(long id) { + public Boolean isExistById(long id) { String sql = "select exists(select id from reservation_time where id = ?)"; return jdbcTemplate.queryForObject(sql, Boolean.class, id); } @Override - public boolean isExistReservationTimeByStartAt(LocalTime startAt) { + public Boolean isExistByStartAt(LocalTime startAt) { String sql = "select exists (select id from reservation_time where start_at = ?)"; return jdbcTemplate.queryForObject(sql, Boolean.class, startAt); } diff --git a/src/main/java/roomescape/repository/dao/JdbcThemeDao.java b/src/main/java/roomescape/repository/dao/JdbcThemeDao.java index fd7d0c4c39..da8a368073 100644 --- a/src/main/java/roomescape/repository/dao/JdbcThemeDao.java +++ b/src/main/java/roomescape/repository/dao/JdbcThemeDao.java @@ -5,10 +5,10 @@ import org.springframework.stereotype.Repository; import roomescape.model.Theme; -import java.time.LocalDate; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; @Repository public class JdbcThemeDao implements ThemeDao { @@ -24,7 +24,16 @@ public JdbcThemeDao(JdbcTemplate jdbcTemplate) { } @Override - public List findAllThemes() { + public long save(Theme theme) { + Map parameters = new HashMap<>(3); + parameters.put("name", theme.getName()); + parameters.put("description", theme.getDescription()); + parameters.put("thumbnail", theme.getThumbnail()); + return insertActor.executeAndReturnKey(parameters).longValue(); + } + + @Override + public List findAll() { String sql = "select id, name, description, thumbnail from theme"; return jdbcTemplate.query(sql, (resultSet, rowNum) -> new Theme( @@ -36,50 +45,21 @@ public List findAllThemes() { } @Override - public Theme saveTheme(Theme theme) { - Map parameters = new HashMap<>(1); - parameters.put("name", theme.getName()); - parameters.put("description", theme.getDescription()); - parameters.put("thumbnail", theme.getThumbnail()); - Number newId = insertActor.executeAndReturnKey(parameters); - return new Theme(newId.longValue(), theme.getName(), theme.getDescription(), theme.getThumbnail()); - } - - @Override - public void deleteThemeById(long id) { - String sql = "delete from theme where id = ?"; - jdbcTemplate.update(sql, id); - } - - @Override - public Theme findThemeById(long id) { + public Optional findById(long id) { String sql = "select id, name, description, thumbnail from theme where id = ?"; - return jdbcTemplate.queryForObject(sql, (resultSet, ignored) -> + Theme theme = jdbcTemplate.queryForObject(sql, (resultSet, rowNum) -> new Theme( resultSet.getLong("id"), resultSet.getString("name"), resultSet.getString("description"), resultSet.getString("thumbnail") ), id); + return Optional.ofNullable(theme); } @Override - public List findThemeRankingByDate(LocalDate before, LocalDate after, int limit) { - String sql = """ - select th.id, th.name, th.description, th.thumbnail - from reservation as r - inner join theme as th on r.theme_id = th.id - where r.date between ? and ? - group by r.theme_id - order by count(r.theme_id) desc - limit ? - """; - return jdbcTemplate.query(sql, (resultSet, ignored) -> - new Theme( - resultSet.getLong("id"), - resultSet.getString("name"), - resultSet.getString("description"), - resultSet.getString("thumbnail") - ), before, after, limit); + public void deleteById(long id) { + String sql = "delete from theme where id = ?"; + jdbcTemplate.update(sql, id); } } diff --git a/src/main/java/roomescape/repository/dao/ReservationDao.java b/src/main/java/roomescape/repository/dao/ReservationDao.java index a848ff793d..d8557a0a68 100644 --- a/src/main/java/roomescape/repository/dao/ReservationDao.java +++ b/src/main/java/roomescape/repository/dao/ReservationDao.java @@ -1,26 +1,29 @@ package roomescape.repository.dao; import roomescape.model.Reservation; -import roomescape.model.ReservationTime; +import roomescape.repository.dto.ReservationSavedDto; import java.time.LocalDate; import java.util.List; +import java.util.Optional; public interface ReservationDao { - List findAllReservations(); + long save(Reservation reservation); - Reservation saveReservation(Reservation reservation); + List findAll(); - void deleteReservationById(long id); + Optional findById(long id); - boolean isExistReservationById(long id); + List findByDateAndThemeId(LocalDate date, long themeId); - boolean isExistReservationByTimeId(long timeId); + List findByDateAndGroupByThemeIdAndOrderByCountAndLimit(LocalDate startDate, LocalDate endDate, int limit); + // TODO: decide naming + void deleteById(long id); - boolean isExistReservationByDateAndTimeId(LocalDate date, long timeId); + Boolean isExistById(long id); - List findReservationTimeBooked(LocalDate date, long themeId); + Boolean isExistByTimeId(long timeId); - List findReservationTimeNotBooked(LocalDate date, long themeId); + Boolean isExistByDateAndTimeId(LocalDate date, long timeId); } diff --git a/src/main/java/roomescape/repository/dao/ReservationTimeDao.java b/src/main/java/roomescape/repository/dao/ReservationTimeDao.java index 15d835fea4..d2848a6d5f 100644 --- a/src/main/java/roomescape/repository/dao/ReservationTimeDao.java +++ b/src/main/java/roomescape/repository/dao/ReservationTimeDao.java @@ -4,18 +4,19 @@ import java.time.LocalTime; import java.util.List; +import java.util.Optional; public interface ReservationTimeDao { - List findAllReservationTimes(); + long save(ReservationTime reservationTime); - ReservationTime findReservationTimeById(long id); + List findAll(); - ReservationTime saveReservationTime(ReservationTime reservationTime); + Optional findById(long id); - void deleteReservationTimeById(long id); + void deleteById(long id); - boolean isExistReservationTimeById(long id); + Boolean isExistById(long id); - boolean isExistReservationTimeByStartAt(LocalTime startAt); + Boolean isExistByStartAt(LocalTime startAt); } diff --git a/src/main/java/roomescape/repository/dao/ThemeDao.java b/src/main/java/roomescape/repository/dao/ThemeDao.java index f79503fa90..a99fa8c096 100644 --- a/src/main/java/roomescape/repository/dao/ThemeDao.java +++ b/src/main/java/roomescape/repository/dao/ThemeDao.java @@ -2,18 +2,16 @@ import roomescape.model.Theme; -import java.time.LocalDate; import java.util.List; +import java.util.Optional; public interface ThemeDao { - List findAllThemes(); + long save(Theme theme); - Theme saveTheme(Theme theme); + List findAll(); - void deleteThemeById(long id); + Optional findById(long id); - Theme findThemeById(long id); - - List findThemeRankingByDate(LocalDate before, LocalDate after, int limit); + void deleteById(long id); } diff --git a/src/main/java/roomescape/repository/dto/ReservationSavedDto.java b/src/main/java/roomescape/repository/dto/ReservationSavedDto.java new file mode 100644 index 0000000000..c43a1c3f2b --- /dev/null +++ b/src/main/java/roomescape/repository/dto/ReservationSavedDto.java @@ -0,0 +1,54 @@ +package roomescape.repository.dto; + +import java.time.LocalDate; +import java.util.Objects; + +public class ReservationSavedDto { + + private final long id; + private final String name; + private final LocalDate date; + private final long timeId; + private final long themeId; + + public ReservationSavedDto(long id, String name, LocalDate date, Long timeId, Long themeId) { + this.id = id; + this.name = name; + this.date = date; + this.timeId = timeId; + this.themeId = themeId; + } + + public long getId() { + return id; + } + + public String getName() { + return name; + } + + public LocalDate getDate() { + return date; + } + + public long getTimeId() { + return timeId; + } + + public long getThemeId() { + return themeId; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ReservationSavedDto that = (ReservationSavedDto) o; + return id == that.id && timeId == that.timeId && themeId == that.themeId && Objects.equals(name, that.name) && Objects.equals(date, that.date); + } + + @Override + public int hashCode() { + return Objects.hash(id, name, date, timeId, themeId); + } +} diff --git a/src/main/java/roomescape/service/ReservationService.java b/src/main/java/roomescape/service/ReservationService.java index 3ae3aaf2da..5c67e023de 100644 --- a/src/main/java/roomescape/service/ReservationService.java +++ b/src/main/java/roomescape/service/ReservationService.java @@ -35,8 +35,10 @@ public Reservation saveReservation(ReservationDto reservationDto) { LocalDate date = reservationDto.getDate(); long timeId = reservationDto.getTimeId(); long themeId = reservationDto.getThemeId(); - ReservationTime time = reservationRepository.findReservationTimeById(timeId); - Theme theme = reservationRepository.findThemeById(themeId); + ReservationTime time = reservationRepository.findReservationTimeById(timeId) + .orElseThrow(() -> new BadRequestException("[ERROR] 데이터가 저장되지 않습니다.")); + Theme theme = reservationRepository.findThemeById(themeId) + .orElseThrow(() -> new BadRequestException("[ERROR] 데이터가 저장되지 않습니다.")); validate(date, time); Reservation reservation = new Reservation(name, date, time, theme); diff --git a/src/main/java/roomescape/service/ReservationTimeService.java b/src/main/java/roomescape/service/ReservationTimeService.java index 1514a3ff48..8c5f306dd9 100644 --- a/src/main/java/roomescape/service/ReservationTimeService.java +++ b/src/main/java/roomescape/service/ReservationTimeService.java @@ -28,7 +28,8 @@ public ReservationTime saveReservationTime(ReservationTimeDto reservationTimeDto LocalTime startAt = reservationTimeDto.getStartAt(); validateDuplication(startAt); ReservationTime reservationTime = new ReservationTime(reservationTimeDto.getStartAt()); - return reservationTimeRepository.saveReservationTime(reservationTime); + return reservationTimeRepository.saveReservationTime(reservationTime) + .orElseThrow(() -> new BadRequestException("[ERROR] 데이터가 저장되지 않습니다.")); } private void validateDuplication(LocalTime startAt) { @@ -39,7 +40,8 @@ private void validateDuplication(LocalTime startAt) { } public ReservationTime findReservationTime(long id) { - return reservationTimeRepository.findReservationById(id); + return reservationTimeRepository.findReservationById(id) + .orElseThrow(() -> new BadRequestException("[ERROR] 데이터가 저장되지 않습니다.")); } public void deleteReservationTime(long id) { diff --git a/src/main/java/roomescape/service/ThemeService.java b/src/main/java/roomescape/service/ThemeService.java index 56adfb62a5..8bffd55f65 100644 --- a/src/main/java/roomescape/service/ThemeService.java +++ b/src/main/java/roomescape/service/ThemeService.java @@ -1,6 +1,7 @@ package roomescape.service; import org.springframework.stereotype.Service; +import roomescape.exception.BadRequestException; import roomescape.model.Theme; import roomescape.repository.ThemeRepository; import roomescape.service.dto.ThemeDto; @@ -26,7 +27,8 @@ public List findAllThemes() { public Theme saveTheme(ThemeDto themeDto) { Theme theme = Theme.from(themeDto); - return themeRepository.saveTheme(theme); + return themeRepository.saveTheme(theme) + .orElseThrow(() -> new BadRequestException("[ERROR] 데이터가 저장되지 않습니다.")); } public void deleteTheme(long id) { diff --git a/src/test/java/roomescape/controller/ThemeControllerTest.java b/src/test/java/roomescape/controller/ThemeControllerTest.java index ff9cbfe565..f9a72b942f 100644 --- a/src/test/java/roomescape/controller/ThemeControllerTest.java +++ b/src/test/java/roomescape/controller/ThemeControllerTest.java @@ -126,16 +126,16 @@ void should_find_popular_theme() { assertThat(popularThemes).hasSize(10); assertAll(() -> { - assertThat(popularThemes.get(0).getThemeId()).isEqualTo(10); - assertThat(popularThemes.get(1).getThemeId()).isEqualTo(9); - assertThat(popularThemes.get(2).getThemeId()).isEqualTo(1); - assertThat(popularThemes.get(3).getThemeId()).isEqualTo(2); - assertThat(popularThemes.get(4).getThemeId()).isEqualTo(3); - assertThat(popularThemes.get(5).getThemeId()).isEqualTo(4); - assertThat(popularThemes.get(6).getThemeId()).isEqualTo(5); - assertThat(popularThemes.get(7).getThemeId()).isEqualTo(6); - assertThat(popularThemes.get(8).getThemeId()).isEqualTo(7); - assertThat(popularThemes.get(9).getThemeId()).isEqualTo(8); + assertThat(popularThemes.get(0).getId()).isEqualTo(10); + assertThat(popularThemes.get(1).getId()).isEqualTo(9); + assertThat(popularThemes.get(2).getId()).isEqualTo(1); + assertThat(popularThemes.get(3).getId()).isEqualTo(2); + assertThat(popularThemes.get(4).getId()).isEqualTo(3); + assertThat(popularThemes.get(5).getId()).isEqualTo(4); + assertThat(popularThemes.get(6).getId()).isEqualTo(5); + assertThat(popularThemes.get(7).getId()).isEqualTo(6); + assertThat(popularThemes.get(8).getId()).isEqualTo(7); + assertThat(popularThemes.get(9).getId()).isEqualTo(8); }); } diff --git a/src/test/java/roomescape/repository/ReservationDaoTest.java b/src/test/java/roomescape/repository/ReservationDaoTest.java index d3a38be070..1bc8afd90e 100644 --- a/src/test/java/roomescape/repository/ReservationDaoTest.java +++ b/src/test/java/roomescape/repository/ReservationDaoTest.java @@ -12,6 +12,7 @@ import roomescape.model.ReservationTime; import roomescape.model.Theme; import roomescape.repository.dao.ReservationDao; +import roomescape.repository.dto.ReservationSavedDto; import java.time.LocalDate; import java.time.LocalTime; @@ -88,15 +89,15 @@ private void insertTheme(String name, String description, String thumbnail) { @DisplayName("모든 예약을 조회한다") @Test void should_get_reservation() { - List reservations = reservationDao.findAllReservations(); + List reservations = reservationDao.findAll(); assertThat(reservations).hasSize(2); } @DisplayName("조회한 예약에 예약 시간이 존재한다.") @Test void should_get_reservation_times() { - List reservations = reservationDao.findAllReservations(); - assertThat(reservations.get(0).getTime().getStartAt()).isEqualTo(LocalTime.of(10, 0)); + List reservations = reservationDao.findAll(); + assertThat(reservations.get(0).getTimeId()).isEqualTo(1); } @DisplayName("예약을 추가한다") @@ -106,7 +107,7 @@ void should_add_reservation() { Theme theme = new Theme(1, "에버", "공포", "공포.jpg"); Reservation reservation = new Reservation("네오", LocalDate.of(2024, 9, 1), reservationTime, theme); - reservationDao.saveReservation(reservation); + reservationDao.save(reservation); Integer count = jdbcTemplate.queryForObject("select count(1) from reservation", Integer.class); assertThat(count).isEqualTo(3); @@ -115,7 +116,7 @@ void should_add_reservation() { @DisplayName("예약을 삭제한다") @Test void should_delete_reservation() { - reservationDao.deleteReservationById(1); + reservationDao.deleteById(1); Integer count = jdbcTemplate.queryForObject("select count(1) from reservation", Integer.class); assertThat(count).isEqualTo(1); } @@ -123,23 +124,23 @@ void should_delete_reservation() { @DisplayName("특정 id를 가진 데이터가 존재하면 참을 반환한다.") @Test void should_return_true_when_exist() { - boolean isExist = reservationDao.isExistReservationById(1); + boolean isExist = reservationDao.isExistById(1); assertThat(isExist).isTrue(); } @DisplayName("특정 id를 가진 데이터가 존재하지 않으면 거짓을 반환한다.") @Test void should_return_false_when_not_exist() { - boolean isExist = reservationDao.isExistReservationById(100000000); + boolean isExist = reservationDao.isExistById(100000000); assertThat(isExist).isFalse(); } - @DisplayName("특정 날짜와 테마에 해당하는 시간을 조회한다.") + @DisplayName("특정 날짜와 테마에 해당하는 예약을 조회한다.") @Test void should_get_reservation_times_when_date_and_theme_given() { LocalDate date = LocalDate.of(2023, 8, 5); - List times = reservationDao.findReservationTimeBooked(date, 1); - assertThat(times).hasSize(1); - assertThat(times).containsExactly(new ReservationTime(1, LocalTime.of(10, 0))); + List reservations = reservationDao.findByDateAndThemeId(date, 1); + assertThat(reservations).hasSize(1); + assertThat(reservations).containsExactly(new ReservationSavedDto(1, "브라운", date, 1L, 1L)); } } diff --git a/src/test/java/roomescape/repository/ReservationTimeDaoTest.java b/src/test/java/roomescape/repository/ReservationTimeDaoTest.java index 7886b0ac62..fe20fc8eb4 100644 --- a/src/test/java/roomescape/repository/ReservationTimeDaoTest.java +++ b/src/test/java/roomescape/repository/ReservationTimeDaoTest.java @@ -52,14 +52,14 @@ private void insertToReservationTime(String startAt) { @DisplayName("모든 예약 시간을 조회한다") @Test void should_get_reservation_times() { - List reservationTimes = reservationTimeDao.findAllReservationTimes(); + List reservationTimes = reservationTimeDao.findAll(); assertThat(reservationTimes).hasSize(2); } @DisplayName("예약 시간을 추가한다") @Test void should_add_reservation_time() { - reservationTimeDao.saveReservationTime(new ReservationTime(LocalTime.of(12, 0))); + reservationTimeDao.save(new ReservationTime(LocalTime.of(12, 0))); Integer count = jdbcTemplate.queryForObject("select count(1) from reservation_time", Integer.class); assertThat(count).isEqualTo(3); } @@ -67,7 +67,7 @@ void should_add_reservation_time() { @DisplayName("예약 시간을 삭제한다") @Test void should_delete_reservation_time() { - reservationTimeDao.deleteReservationTimeById(1); + reservationTimeDao.deleteById(1); Integer count = jdbcTemplate.queryForObject("select count(1) from reservation_time", Integer.class); assertThat(count).isEqualTo(1); } @@ -75,21 +75,21 @@ void should_delete_reservation_time() { @DisplayName("아이디에 해당하는 예약 시간을 조회한다.") @Test void should_get_reservation_time() { - ReservationTime reservationTime = reservationTimeDao.findReservationTimeById(1); + ReservationTime reservationTime = reservationTimeDao.findById(1).orElse(null); assertThat(reservationTime.getStartAt()).isEqualTo(LocalTime.of(10, 0)); } @DisplayName("특정 id를 갖는 데이터가 존재하는 경우 참을 반환한다.") @Test void should_return_true_when_exist() { - Boolean isExist = reservationTimeDao.isExistReservationTimeById(1); + Boolean isExist = reservationTimeDao.isExistById(1); assertThat(isExist).isTrue(); } @DisplayName("특정 id를 갖는 데이터가 존재하지 않는 경우 거짓을 반환한다.") @Test void should_return_false_when_not_exist() { - Boolean isExist = reservationTimeDao.isExistReservationTimeById(100000000); + Boolean isExist = reservationTimeDao.isExistById(100000000); assertThat(isExist).isFalse(); } } diff --git a/src/test/java/roomescape/repository/ThemeDaoTest.java b/src/test/java/roomescape/repository/ThemeDaoTest.java index 2bed2a8117..182ded9137 100644 --- a/src/test/java/roomescape/repository/ThemeDaoTest.java +++ b/src/test/java/roomescape/repository/ThemeDaoTest.java @@ -11,8 +11,6 @@ import roomescape.model.Theme; import roomescape.repository.dao.ThemeDao; -import java.time.LocalDate; -import java.time.LocalTime; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -62,7 +60,7 @@ private void insertTheme(String name, String description, String thumbnail) { @DisplayName("모든 테마를 조회한다.") @Test void should_find_all_themes() { - List allThemes = themeDao.findAllThemes(); + List allThemes = themeDao.findAll(); assertThat(allThemes).hasSize(2); } @@ -70,17 +68,18 @@ void should_find_all_themes() { @Test void should_add_theme() { Theme theme = new Theme("브라운", "공포", "공포.jpg"); - themeDao.saveTheme(theme); - assertThat(themeDao.findAllThemes()).hasSize(3); + themeDao.save(theme); + assertThat(themeDao.findAll()).hasSize(3); } @DisplayName("테마를 삭제한다.") @Test void should_delete_theme() { - themeDao.deleteThemeById(1); - assertThat(themeDao.findAllThemes()).hasSize(1); + themeDao.deleteById(1); + assertThat(themeDao.findAll()).hasSize(1); } + /* @DisplayName("특정 기간의 테마를 인기순으로 정렬하여 조회한다.") @Test void should_find_ranking_theme_by_date() { @@ -132,4 +131,5 @@ private void insertReservation(String name, LocalDate date, long timeId, long th parameters.put("theme_id", themeId); reservationInsertActor.execute(parameters); } -} \ No newline at end of file + */ +} diff --git a/src/test/java/roomescape/service/FakeReservationDao.java b/src/test/java/roomescape/service/FakeReservationDao.java index 020058829c..db7528da37 100644 --- a/src/test/java/roomescape/service/FakeReservationDao.java +++ b/src/test/java/roomescape/service/FakeReservationDao.java @@ -1,78 +1,142 @@ package roomescape.service; import roomescape.model.Reservation; -import roomescape.model.ReservationTime; -import roomescape.model.Theme; import roomescape.repository.dao.ReservationDao; +import roomescape.repository.dto.ReservationSavedDto; import java.time.LocalDate; -import java.time.LocalTime; -import java.util.ArrayList; -import java.util.List; -import java.util.NoSuchElementException; +import java.util.*; +import java.util.concurrent.atomic.AtomicLong; +import java.util.stream.Collectors; class FakeReservationDao implements ReservationDao { - private List reservationTimes = new ArrayList<>(List.of( - new ReservationTime(1, LocalTime.of(10, 0)), - new ReservationTime(2, LocalTime.of(11, 0)))); + private final AtomicLong index = new AtomicLong(3); // TODO: change to 1 +// private final List reservationTimes = new ArrayList<>(List.of( +// new ReservationTime(1, LocalTime.of(10, 0)), +// new ReservationTime(2, LocalTime.of(11, 0)))); +// +// private final List themes = new ArrayList<>(List.of( +// new Theme(1, "에버", "공포", "공포.jpg"), +// new Theme(1, "배키", "스릴러", "스릴러.jpg"))); - private List reservations = new ArrayList<>(List.of( - new Reservation(1, "브라운", LocalDate.of(2030, 8, 5), - new ReservationTime(2, LocalTime.of(11, 0)), - new Theme(1, "에버", "공포", "공포.jpg")), - new Reservation(1, "리사", LocalDate.of(2030, 8, 1), - new ReservationTime(2, LocalTime.of(11, 0)), - new Theme(2, "배키", "스릴러", "스릴러.jpg")))); + private final List reservations; + + public FakeReservationDao(List reservations) { +// for (ReservationSavedDto dto : reservations) { +// Reservation reservation = new Reservation(dto.getName(), dto.getDate(), dto.); +// } TODO + this.reservations = reservations; + } @Override - public List findAllReservations() { - return reservations; + public List findAll() { + return Collections.unmodifiableList(reservations); } @Override - public Reservation saveReservation(Reservation reservation) { - reservations.add(reservation); - return reservation; + public long save(Reservation reservation) { + long key = index.getAndIncrement(); + ReservationSavedDto saved = new ReservationSavedDto(key, reservation.getName(), reservation.getDate(), reservation.getTime().getId(), reservation.getTheme().getId()); + reservations.add(saved); + return key; } @Override - public void deleteReservationById(long id) { - Reservation foundReservation = reservations.stream() + public Optional findById(long id) { + return reservations.stream() .filter(reservation -> reservation.getId() == id) - .findFirst() - .orElseThrow(() -> new NoSuchElementException("아이디가 존재하지 않습니다.")); - reservations.remove(foundReservation); + .findFirst(); } @Override - public boolean isExistReservationById(long id) { - return reservations.stream().anyMatch(reservation -> reservation.getId() == id); + public List findByDateAndThemeId(LocalDate date, long themeId) { + return reservations.stream() + .filter(reservation -> reservation.getDate().equals(date) && reservation.getThemeId() == themeId) + .toList(); } @Override - public boolean isExistReservationByTimeId(long timeId) { - return reservations.stream().anyMatch(reservation -> reservation.getTime().getId() == timeId); + public List findByDateAndGroupByThemeIdAndOrderByCountAndLimit(LocalDate startDate, LocalDate endDate, int limit) { + // Filter reservations by date + List filteredReservations = reservations.stream() + .filter(reservation -> reservation.getDate().isAfter(startDate) && reservation.getDate().isBefore(endDate)) + .toList(); + + // Count reservations by themeId + Map countOfThemeIds = filteredReservations.stream() + .collect(Collectors.groupingBy(ReservationSavedDto::getThemeId, Collectors.counting())); + // Sort themeIds by count + List finalThemeIds = countOfThemeIds.entrySet().stream() + .sorted(Map.Entry.comparingByValue().reversed()) + .limit(10) + .map(Map.Entry::getKey) + .toList(); + // Filter reservations by top 10 themeIds + return finalThemeIds; + + /* + // find by date + List filteredReservations = reservations.stream() + .filter(reservation -> reservation.getDate().isBefore(endDate) && reservation.getDate().isAfter(startDate)) + .toList(); + + // group by themeId + List filteredThemeIds = filteredReservations.stream() + .map(ReservationSavedDto::getThemeId) + .collect(Collectors.toList()); + + // order by count + Map countOfThemeIds = new HashMap<>(); + for (Long filteredThemeId : filteredThemeIds) { + long count = filteredThemeIds.stream() + .filter(id -> id.equals(filteredThemeId)) + .count(); + countOfThemeIds.put(filteredThemeId, count); + } + filteredThemeIds.sort(Comparator.comparingLong(countOfThemeIds::get)); + + // limit 10 + List themeIds = filteredThemeIds.stream().distinct().toList(); + List finalThemeIds = themeIds.subList(0, 10); + + // make DTO + List result = new ArrayList<>(); + for (Long finalThemeId : finalThemeIds) { + result.add(filteredReservations.stream() + .filter(reservation -> reservation.getThemeId() == finalThemeId) + .findFirst() + .orElseThrow(NoSuchElementException::new)); + } + return result; + + */ } @Override - public boolean isExistReservationByDateAndTimeId(LocalDate date, long timeId) { + public void deleteById(long id) { + ReservationSavedDto foundReservation = reservations.stream() + .filter(reservation -> reservation.getId() == id) + .findFirst() + .orElseThrow(() -> new NoSuchElementException("아이디가 존재하지 않습니다.")); + reservations.remove(foundReservation); + } + + @Override + public Boolean isExistById(long id) { return reservations.stream() - .anyMatch(reservation -> reservation.getDate().isEqual(date) && reservation.getTime().getId() == timeId); + .anyMatch(reservation -> reservation.getId() == id); } @Override - public List findReservationTimeBooked(LocalDate date, long themeId) { + public Boolean isExistByTimeId(long timeId) { return reservations.stream() - .filter(reservation -> reservation.getDate().equals(date) && reservation.getTheme().getId() == themeId) - .map(reservation -> new ReservationTime(reservation.getTime().getId(), reservation.getTime().getStartAt())) - .toList(); + .anyMatch(reservation -> reservation.getTimeId() == timeId); } @Override - public List findReservationTimeNotBooked(LocalDate date, long themeId) { - List all = new ArrayList<>(reservationTimes); - all.removeAll(findReservationTimeBooked(date, themeId)); - return all; + public Boolean isExistByDateAndTimeId(LocalDate date, long timeId) { + return reservations.stream() + .anyMatch(reservation -> reservation.getDate().isEqual(date) && reservation.getTimeId() == timeId); } } \ No newline at end of file diff --git a/src/test/java/roomescape/service/FakeReservationTimeDao.java b/src/test/java/roomescape/service/FakeReservationTimeDao.java index 79381d923a..7c1e13d45d 100644 --- a/src/test/java/roomescape/service/FakeReservationTimeDao.java +++ b/src/test/java/roomescape/service/FakeReservationTimeDao.java @@ -7,54 +7,53 @@ import java.util.ArrayList; import java.util.List; import java.util.NoSuchElementException; +import java.util.Optional; +import java.util.concurrent.atomic.AtomicLong; class FakeReservationTimeDao implements ReservationTimeDao { - private final List reservationTimes = new ArrayList<>(List.of( - new ReservationTime(1, LocalTime.of(10, 0)), - new ReservationTime(2, LocalTime.of(11, 0)) - )); + private final AtomicLong index = new AtomicLong(1); + private final List reservationTimes = new ArrayList<>(); - public void add(ReservationTime reservationTime) { - reservationTimes.add(reservationTime); + public FakeReservationTimeDao(List reservationTimes) { + reservationTimes.forEach(this::save); } @Override - public List findAllReservationTimes() { - return reservationTimes; + public long save(ReservationTime reservationTime) { + long key = index.getAndIncrement(); + reservationTimes.add(new ReservationTime(key, reservationTime.getStartAt())); + return key; } @Override - public ReservationTime findReservationTimeById(long id) { - return reservationTimes.stream() - .filter(reservationTime -> reservationTime.getId() == id) - .findFirst() - .orElseThrow(() -> new NoSuchElementException("해당하는 아이디가 없습니다.")); + public List findAll() { + return reservationTimes; } @Override - public ReservationTime saveReservationTime(ReservationTime reservationTime) { - reservationTimes.add(reservationTime); - return new ReservationTime(3, reservationTime.getStartAt()); + public Optional findById(long id) { + return reservationTimes.stream() + .filter(reservationTime -> reservationTime.getId() == id) + .findFirst(); } @Override - public void deleteReservationTimeById(long id) { + public void deleteById(long id) { ReservationTime findReservationTime = reservationTimes.stream() .filter(reservationTime -> reservationTime.getId() == id) .findFirst() .orElseThrow(() -> new NoSuchElementException("해당하는 아이디가 없습니다.")); - reservationTimes.remove(findReservationTime); } @Override - public boolean isExistReservationTimeById(long id) { + public Boolean isExistById(long id) { return reservationTimes.stream().anyMatch(reservationTime -> reservationTime.getId() == id); } @Override - public boolean isExistReservationTimeByStartAt(LocalTime startAt) { - return reservationTimes.stream().anyMatch(reservationTime -> reservationTime.getStartAt() == startAt); + public Boolean isExistByStartAt(LocalTime startAt) { + return reservationTimes.stream().anyMatch(reservationTime -> reservationTime.getStartAt().equals(startAt)); } } diff --git a/src/test/java/roomescape/service/FakeThemeDao.java b/src/test/java/roomescape/service/FakeThemeDao.java index ccdbb3d95d..52be902008 100644 --- a/src/test/java/roomescape/service/FakeThemeDao.java +++ b/src/test/java/roomescape/service/FakeThemeDao.java @@ -3,36 +3,35 @@ import roomescape.model.Theme; import roomescape.repository.dao.ThemeDao; -import java.time.LocalDate; import java.util.ArrayList; import java.util.List; import java.util.NoSuchElementException; +import java.util.Optional; import java.util.concurrent.atomic.AtomicLong; public class FakeThemeDao implements ThemeDao { - private List themes = new ArrayList<>(List.of( - new Theme(1, "에버", "공포", "공포.jpg"), - new Theme(2, "배키", "미스터리", "미스터리.jpg"), - new Theme(3, "포비", "스릴러", "스릴러.jpg") - )); + private final AtomicLong index = new AtomicLong(1L); + private final List themes = new ArrayList<>(); - private AtomicLong index = new AtomicLong(1L); + public FakeThemeDao(List themes) { + themes.forEach(this::save); + } @Override - public List findAllThemes() { + public List findAll() { return themes; } @Override - public Theme saveTheme(Theme theme) { - Theme newTheme = new Theme(index.getAndIncrement(), theme.getName(), theme.getDescription(), theme.getThumbnail()); - themes.add(newTheme); - return newTheme; + public long save(Theme theme) { + long key = index.getAndIncrement(); + themes.add(new Theme(key, theme.getName(), theme.getDescription(), theme.getThumbnail())); + return key; } @Override - public void deleteThemeById(long id) { + public void deleteById(long id) { Theme targetTheme = themes.stream() .filter(theme -> theme.getId() == id) .findFirst() @@ -41,26 +40,9 @@ public void deleteThemeById(long id) { } @Override - public Theme findThemeById(long id) { + public Optional findById(long id) { return themes.stream() .filter(theme -> theme.getId() == id) - .findFirst() - .orElseThrow(() -> new NoSuchElementException("존재하지 않는 테마입니다.")); - } - - @Override - public List findThemeRankingByDate(LocalDate before, LocalDate after, int limit) { - return List.of( - new Theme(10, "name10", "description10", "thumbnail10"), - new Theme(9, "name9", "description9", "thumbnail9"), - new Theme(1, "name1", "description1", "thumbnail1"), - new Theme(2, "name2", "description2", "thumbnail2"), - new Theme(3, "name3", "description3", "thumbnail3"), - new Theme(4, "name4", "description4", "thumbnail4"), - new Theme(5, "name5", "description5", "thumbnail5"), - new Theme(6, "name6", "description6", "thumbnail6"), - new Theme(7, "name7", "description7", "thumbnail7"), - new Theme(8, "name8", "description8", "thumbnail8") - ); + .findFirst(); } } diff --git a/src/test/java/roomescape/service/ReservationServiceTest.java b/src/test/java/roomescape/service/ReservationServiceTest.java index d3d8e428a4..04697b912a 100644 --- a/src/test/java/roomescape/service/ReservationServiceTest.java +++ b/src/test/java/roomescape/service/ReservationServiceTest.java @@ -1,5 +1,6 @@ package roomescape.service; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import roomescape.controller.response.MemberReservationTimeResponse; @@ -8,25 +9,42 @@ import roomescape.exception.NotFoundException; import roomescape.model.Reservation; import roomescape.model.ReservationTime; +import roomescape.model.Theme; import roomescape.repository.ReservationRepository; +import roomescape.repository.dao.ReservationDao; import roomescape.repository.dao.ReservationTimeDao; +import roomescape.repository.dao.ThemeDao; +import roomescape.repository.dto.ReservationSavedDto; import roomescape.service.dto.ReservationDto; import java.time.LocalDate; import java.time.LocalTime; +import java.util.ArrayList; import java.util.List; import static org.assertj.core.api.Assertions.*; class ReservationServiceTest { - private final ReservationTimeDao reservationTimeDao = new FakeReservationTimeDao(); - private final ReservationRepository reservationRepository = new ReservationRepository( - new FakeReservationDao(), reservationTimeDao, new FakeThemeDao()); -// private ReservationTimeRepository reservationTimeRepository = new ReservationTimeRepository( -// new FakeReservationDao(), new FakeReservationTimeDao()); - private final ReservationService reservationService = new ReservationService(reservationRepository); - + private ReservationService reservationService; + private ReservationRepository reservationRepository; + private ReservationTimeDao reservationTimeDao; // TODO: remove field + + @BeforeEach + void setUp() { // 테케 의존성 분리하기 + ThemeDao themeDao = new FakeThemeDao(new ArrayList<>(List.of( + new Theme(1, "에버", "공포", "공포.jpg"), + new Theme(2, "배키", "미스터리", "미스터리.jpg"), + new Theme(3, "포비", "스릴러", "스릴러.jpg")))); + reservationTimeDao = new FakeReservationTimeDao(new ArrayList<>(List.of( + new ReservationTime(1, LocalTime.of(10, 0)), + new ReservationTime(2, LocalTime.of(11, 0))))); + ReservationDao reservationDao = new FakeReservationDao(new ArrayList<>(List.of( + new ReservationSavedDto(1, "브라운", LocalDate.of(2030, 8, 5), 2L, 1L), + new ReservationSavedDto(1, "리사", LocalDate.of(2030, 8, 1), 2L, 2L)))); + reservationRepository = new ReservationRepository(reservationDao, reservationTimeDao, themeDao); + reservationService = new ReservationService(reservationRepository); + } @DisplayName("모든 예약 시간을 반환한다") @Test @@ -79,8 +97,8 @@ void should_throw_exception_when_previous_date() { @DisplayName("현재로 예약하면 예외가 발생하지 않는다.") @Test void should_not_throw_exception_when_current_date() { - reservationTimeDao.saveReservationTime(new ReservationTime(3, LocalTime.now())); - ReservationDto request = new ReservationDto("에버", LocalDate.now(), 3L, 1L); + long timeId = reservationTimeDao.save(new ReservationTime(3, LocalTime.now())); + ReservationDto request = new ReservationDto("에버", LocalDate.now(), timeId, 1L); assertThatCode(() -> reservationService.saveReservation(request)) .doesNotThrowAnyException(); } diff --git a/src/test/java/roomescape/service/ReservationTimeServiceTest.java b/src/test/java/roomescape/service/ReservationTimeServiceTest.java index 102bb843df..e6203b6573 100644 --- a/src/test/java/roomescape/service/ReservationTimeServiceTest.java +++ b/src/test/java/roomescape/service/ReservationTimeServiceTest.java @@ -1,5 +1,6 @@ package roomescape.service; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import roomescape.exception.BadRequestException; @@ -7,19 +8,34 @@ import roomescape.exception.NotFoundException; import roomescape.model.ReservationTime; import roomescape.repository.ReservationTimeRepository; +import roomescape.repository.dao.ReservationDao; +import roomescape.repository.dao.ReservationTimeDao; +import roomescape.repository.dto.ReservationSavedDto; import roomescape.service.dto.ReservationTimeDto; +import java.time.LocalDate; import java.time.LocalTime; +import java.util.ArrayList; import java.util.List; import static org.assertj.core.api.Assertions.*; class ReservationTimeServiceTest { - private final ReservationTimeRepository reservationTimeRepository = new ReservationTimeRepository( - new FakeReservationDao(), new FakeReservationTimeDao()); + private ReservationTimeRepository reservationTimeRepository; + private ReservationTimeService reservationTimeService; - private final ReservationTimeService reservationTimeService = new ReservationTimeService(reservationTimeRepository); + @BeforeEach + void setUp() { // 테케 의존성 분리하기 + ReservationTimeDao reservationTimeDao = new FakeReservationTimeDao(new ArrayList<>(List.of( + new ReservationTime(1, LocalTime.of(10, 0)), + new ReservationTime(2, LocalTime.of(11, 0))))); + ReservationDao reservationDao = new FakeReservationDao(new ArrayList<>(List.of( + new ReservationSavedDto(1, "브라운", LocalDate.of(2030, 8, 5), 2L, 1L), + new ReservationSavedDto(1, "리사", LocalDate.of(2030, 8, 1), 2L, 2L)))); + reservationTimeRepository = new ReservationTimeRepository(reservationDao, reservationTimeDao); + reservationTimeService = new ReservationTimeService(reservationTimeRepository); + } @DisplayName("모든 예약 시간을 반환한다") @Test diff --git a/src/test/java/roomescape/service/ThemeServiceTest.java b/src/test/java/roomescape/service/ThemeServiceTest.java index 818e673a6b..17a7059c0e 100644 --- a/src/test/java/roomescape/service/ThemeServiceTest.java +++ b/src/test/java/roomescape/service/ThemeServiceTest.java @@ -1,19 +1,38 @@ package roomescape.service; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import roomescape.model.Theme; import roomescape.repository.ThemeRepository; +import roomescape.repository.dao.ReservationDao; +import roomescape.repository.dao.ThemeDao; +import roomescape.repository.dto.ReservationSavedDto; import roomescape.service.dto.ThemeDto; +import java.time.LocalDate; +import java.util.ArrayList; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; class ThemeServiceTest { - private final ThemeRepository themeRepository = new ThemeRepository(new FakeThemeDao()); - private final ThemeService themeService = new ThemeService(themeRepository); + private ThemeService themeService; + private ThemeRepository themeRepository; + + @BeforeEach + void setUp() { // 테케 의존성 분리하기 + ThemeDao themeDao = new FakeThemeDao(new ArrayList<>(List.of( + new Theme(1, "에버", "공포", "공포.jpg"), + new Theme(2, "배키", "미스터리", "미스터리.jpg"), + new Theme(3, "포비", "스릴러", "스릴러.jpg")))); + ReservationDao reservationDao = new FakeReservationDao(new ArrayList<>(List.of( + new ReservationSavedDto(1, "브라운", LocalDate.of(2030, 8, 5), 2L, 1L), + new ReservationSavedDto(1, "리사", LocalDate.of(2030, 8, 1), 2L, 2L)))); + themeRepository = new ThemeRepository(reservationDao, themeDao); + themeService = new ThemeService(themeRepository); + } @DisplayName("테마를 조회한다.") @Test @@ -40,17 +59,7 @@ void should_delete_theme() { @Test void should_find_popular_theme_of_week() { List popularThemes = themeService.findPopularThemes(); - assertThat(popularThemes).containsExactly( - new Theme(10, "name10", "description10", "thumbnail10"), - new Theme(9, "name9", "description9", "thumbnail9"), - new Theme(1, "name1", "description1", "thumbnail1"), - new Theme(2, "name2", "description2", "thumbnail2"), - new Theme(3, "name3", "description3", "thumbnail3"), - new Theme(4, "name4", "description4", "thumbnail4"), - new Theme(5, "name5", "description5", "thumbnail5"), - new Theme(6, "name6", "description6", "thumbnail6"), - new Theme(7, "name7", "description7", "thumbnail7"), - new Theme(8, "name8", "description8", "thumbnail8") - ); + // TODO: now 라서 인기 테마 존재하지 않음 + assertThat(popularThemes).hasSize(0); } } \ No newline at end of file From 0dca0004a8238864b92da4fe7d47160571485454 Mon Sep 17 00:00:00 2001 From: SCY Date: Sun, 5 May 2024 19:24:46 +0900 Subject: [PATCH 51/74] =?UTF-8?q?refactor(daoTest):=20=EB=8B=A8=EC=9C=84?= =?UTF-8?q?=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EB=B3=B4=EC=99=84=20=EB=B0=8F?= =?UTF-8?q?=20=EC=BB=A8=EB=B2=A4=EC=85=98=20=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/ThemeRepository.java | 2 +- .../repository/dao/JdbcReservationDao.java | 2 +- .../repository/dao/ReservationDao.java | 4 +- .../repository/dto/ReservationSavedDto.java | 2 +- .../repository/ReservationDaoTest.java | 161 +++++++++++------- .../repository/ReservationTimeDaoTest.java | 97 +++++++---- .../roomescape/repository/ThemeDaoTest.java | 118 ++++--------- .../service/FakeReservationDao.java | 2 +- 8 files changed, 205 insertions(+), 183 deletions(-) diff --git a/src/main/java/roomescape/repository/ThemeRepository.java b/src/main/java/roomescape/repository/ThemeRepository.java index e4f5e6097a..89df8ba5f0 100644 --- a/src/main/java/roomescape/repository/ThemeRepository.java +++ b/src/main/java/roomescape/repository/ThemeRepository.java @@ -37,7 +37,7 @@ public void deleteThemeById(long id) { public List findThemeRankingByDate(LocalDate startDate, LocalDate endDate, int rankingCount) { List result = new ArrayList<>(); - List themeIds = reservationDao.findByDateAndGroupByThemeIdAndOrderByCountAndLimit(startDate, endDate, rankingCount); + List themeIds = reservationDao.findThemeIdByDateAndOrderByThemeIdCountAndLimit(startDate, endDate, rankingCount); for (long themeId : themeIds) { Theme theme = themeDao.findById(themeId).orElseThrow(NoSuchElementException::new); result.add(theme); diff --git a/src/main/java/roomescape/repository/dao/JdbcReservationDao.java b/src/main/java/roomescape/repository/dao/JdbcReservationDao.java index 63af2bd354..1bba2c2705 100644 --- a/src/main/java/roomescape/repository/dao/JdbcReservationDao.java +++ b/src/main/java/roomescape/repository/dao/JdbcReservationDao.java @@ -73,7 +73,7 @@ public List findByDateAndThemeId(LocalDate date, long theme } @Override - public List findByDateAndGroupByThemeIdAndOrderByCountAndLimit(LocalDate startDate, LocalDate endDate, int limit) { + public List findThemeIdByDateAndOrderByThemeIdCountAndLimit(LocalDate startDate, LocalDate endDate, int limit) { String sql = """ select theme_id from reservation diff --git a/src/main/java/roomescape/repository/dao/ReservationDao.java b/src/main/java/roomescape/repository/dao/ReservationDao.java index d8557a0a68..b128275cbb 100644 --- a/src/main/java/roomescape/repository/dao/ReservationDao.java +++ b/src/main/java/roomescape/repository/dao/ReservationDao.java @@ -17,8 +17,8 @@ public interface ReservationDao { List findByDateAndThemeId(LocalDate date, long themeId); - List findByDateAndGroupByThemeIdAndOrderByCountAndLimit(LocalDate startDate, LocalDate endDate, int limit); - // TODO: decide naming + List findThemeIdByDateAndOrderByThemeIdCountAndLimit(LocalDate startDate, LocalDate endDate, int limit); + void deleteById(long id); Boolean isExistById(long id); diff --git a/src/main/java/roomescape/repository/dto/ReservationSavedDto.java b/src/main/java/roomescape/repository/dto/ReservationSavedDto.java index c43a1c3f2b..499e536b15 100644 --- a/src/main/java/roomescape/repository/dto/ReservationSavedDto.java +++ b/src/main/java/roomescape/repository/dto/ReservationSavedDto.java @@ -11,7 +11,7 @@ public class ReservationSavedDto { private final long timeId; private final long themeId; - public ReservationSavedDto(long id, String name, LocalDate date, Long timeId, Long themeId) { + public ReservationSavedDto(long id, String name, LocalDate date, long timeId, long themeId) { this.id = id; this.name = name; this.date = date; diff --git a/src/test/java/roomescape/repository/ReservationDaoTest.java b/src/test/java/roomescape/repository/ReservationDaoTest.java index 1bc8afd90e..07c04945b7 100644 --- a/src/test/java/roomescape/repository/ReservationDaoTest.java +++ b/src/test/java/roomescape/repository/ReservationDaoTest.java @@ -19,48 +19,53 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) -@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) +@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) class ReservationDaoTest { - @Autowired - private JdbcTemplate jdbcTemplate; - - @Autowired - private ReservationDao reservationDao; + private static final int INITIAL_RESERVATION_COUNT = 2; - private SimpleJdbcInsert reservationTimeInsertActor; - private SimpleJdbcInsert reservationInsertActor; - private SimpleJdbcInsert themeInsertActor; + private final JdbcTemplate jdbcTemplate; + private final ReservationDao reservationDao; + private final SimpleJdbcInsert themeInsertActor; + private final SimpleJdbcInsert reservationTimeInsertActor; + private final SimpleJdbcInsert reservationInsertActor; - @BeforeEach - void setUp() { - jdbcTemplate.execute("TRUNCATE TABLE reservation RESTART IDENTITY"); - jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY FALSE"); - jdbcTemplate.execute("TRUNCATE TABLE reservation_time RESTART IDENTITY"); - jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY TRUE"); - - reservationTimeInsertActor = new SimpleJdbcInsert(jdbcTemplate) + @Autowired + public ReservationDaoTest(JdbcTemplate jdbcTemplate, ReservationDao reservationDao) { + this.jdbcTemplate = jdbcTemplate; + this.reservationDao = reservationDao; + this.themeInsertActor = new SimpleJdbcInsert(jdbcTemplate) + .withTableName("theme") + .usingGeneratedKeyColumns("id"); + this.reservationTimeInsertActor = new SimpleJdbcInsert(jdbcTemplate) .withTableName("reservation_time") .usingGeneratedKeyColumns("id"); - reservationInsertActor = new SimpleJdbcInsert(jdbcTemplate) + this.reservationInsertActor = new SimpleJdbcInsert(jdbcTemplate) .withTableName("reservation") .usingGeneratedKeyColumns("id"); - themeInsertActor = new SimpleJdbcInsert(jdbcTemplate) - .withTableName("theme") - .usingGeneratedKeyColumns("id"); - - insertReservationTime("10:00"); - insertReservationTime("11:00"); + } - insertTheme("에버", "공포", "공포.jpg"); - insertTheme("배키", "스릴러", "스릴러.jpg"); + @BeforeEach + void setUp() { + initDatabase(); + insertTheme("n1", "d1", "t1"); + insertTheme("n2", "d2", "t2"); + insertReservationTime("1:00"); + insertReservationTime("2:00"); + insertReservation("n1", "2000-01-01", 1, 1); + insertReservation("n2", "2000-01-02", 2, 2); + } - insertReservation("브라운", "2023-08-05", "1", "1"); - insertReservation("리사", "2023-08-01", "2", "2"); + private void initDatabase() { + jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY FALSE"); + jdbcTemplate.execute("TRUNCATE TABLE theme RESTART IDENTITY"); + jdbcTemplate.execute("TRUNCATE TABLE reservation_time RESTART IDENTITY"); + jdbcTemplate.execute("TRUNCATE TABLE reservation RESTART IDENTITY"); } private void insertReservationTime(String startAt) { @@ -69,7 +74,7 @@ private void insertReservationTime(String startAt) { reservationTimeInsertActor.execute(parameters); } - private void insertReservation(String name, String date, String timeId, String themeId) { + private void insertReservation(String name, String date, long timeId, long themeId) { Map parameters = new HashMap<>(3); parameters.put("name", name); parameters.put("date", date); @@ -86,61 +91,101 @@ private void insertTheme(String name, String description, String thumbnail) { themeInsertActor.execute(parameters); } - @DisplayName("모든 예약을 조회한다") + @DisplayName("예약을 저장한다.") @Test - void should_get_reservation() { - List reservations = reservationDao.findAll(); - assertThat(reservations).hasSize(2); + void should_save_reservation() { + Theme theme = new Theme(1, "n1", "d1", "t1"); + ReservationTime time = new ReservationTime(1, LocalTime.of(1, 0)); + Reservation reservation = new Reservation("n3", LocalDate.of(2000, 1, 3), time, theme); + + reservationDao.save(reservation); + + assertThat(reservationDao.findAll()).hasSize(INITIAL_RESERVATION_COUNT + 1); } - @DisplayName("조회한 예약에 예약 시간이 존재한다.") + @DisplayName("모든 예약을 조회한다.") @Test - void should_get_reservation_times() { + void should_find_all_reservations() { List reservations = reservationDao.findAll(); - assertThat(reservations.get(0).getTimeId()).isEqualTo(1); + assertThat(reservations).hasSize(INITIAL_RESERVATION_COUNT); } - @DisplayName("예약을 추가한다") + @DisplayName("특정 id의 예약을 조회한다.") @Test - void should_add_reservation() { - ReservationTime reservationTime = new ReservationTime(1, LocalTime.of(10, 0)); - Theme theme = new Theme(1, "에버", "공포", "공포.jpg"); - Reservation reservation = new Reservation("네오", LocalDate.of(2024, 9, 1), reservationTime, theme); + void should_find_reservation_by_id() { + ReservationSavedDto expected = new ReservationSavedDto(1, "n1", LocalDate.of(2000, 1, 1), 1L, 1L); - reservationDao.save(reservation); + Optional actual = reservationDao.findById(1); + + assertThat(actual).isNotEmpty(); + assertThat(actual).hasValue(expected); + } + + @DisplayName("특정 date 와 theme_id의 예약을 조회한다.") + @Test + void should_find_reservation_by_date_and_themeId() { + ReservationSavedDto expected = new ReservationSavedDto(1, "n1", LocalDate.of(2000, 1, 1), 1L, 1L); - Integer count = jdbcTemplate.queryForObject("select count(1) from reservation", Integer.class); - assertThat(count).isEqualTo(3); + List actual = reservationDao.findByDateAndThemeId(LocalDate.of(2000, 1, 1), 1); + + assertThat(actual).containsExactly(expected); + } + + @DisplayName("두 date 사이의 예약을, 테마의 개수로 내림차순 정렬하여, 특정 개수의 테마 id를 조회한다.") + @Test + void should_find_themeId_between_date_and_order_by_themeId_count_and_limit() { + List themeIds = reservationDao.findThemeIdByDateAndOrderByThemeIdCountAndLimit( + LocalDate.of(2000, 1, 1), LocalDate.of(2000, 1, 2), 10); + + assertThat(themeIds).containsExactly(1L, 2L); } - @DisplayName("예약을 삭제한다") + @DisplayName("예약을 삭제한다.") @Test void should_delete_reservation() { reservationDao.deleteById(1); - Integer count = jdbcTemplate.queryForObject("select count(1) from reservation", Integer.class); - assertThat(count).isEqualTo(1); + assertThat(reservationDao.findAll()).hasSize(INITIAL_RESERVATION_COUNT - 1); } - @DisplayName("특정 id를 가진 데이터가 존재하면 참을 반환한다.") + @DisplayName("특정 id를 가진 예약이 존재하면 참을 반환한다.") @Test - void should_return_true_when_exist() { + void should_return_true_when_exist_id() { boolean isExist = reservationDao.isExistById(1); assertThat(isExist).isTrue(); } - @DisplayName("특정 id를 가진 데이터가 존재하지 않으면 거짓을 반환한다.") + @DisplayName("특정 id를 가진 예약이 존재하지 않으면 거짓을 반환한다.") + @Test + void should_return_false_when_not_exist_id() { + boolean isExist = reservationDao.isExistById(999); + assertThat(isExist).isFalse(); + } + + @DisplayName("특정 time_id를 가진 예약이 존재하면 참을 반환한다.") + @Test + void should_return_true_when_exist_timeId() { + boolean isExist = reservationDao.isExistByTimeId(1); + assertThat(isExist).isTrue(); + } + + @DisplayName("특정 time_id를 가진 예약이 존재하지 않으면 거짓을 반환한다.") @Test - void should_return_false_when_not_exist() { - boolean isExist = reservationDao.isExistById(100000000); + void should_return_false_when_not_exist_timeId() { + boolean isExist = reservationDao.isExistByTimeId(999); assertThat(isExist).isFalse(); } - @DisplayName("특정 날짜와 테마에 해당하는 예약을 조회한다.") + @DisplayName("특정 date와 time_id를 가진 예약이 존재하면 참을 반환한다.") + @Test + void should_return_true_when_exist_date_and_timeId() { + boolean isExist = reservationDao.isExistByDateAndTimeId(LocalDate.of(2000, 1, 1), 1); + assertThat(isExist).isTrue(); + } + + @DisplayName("특정 date와 time_id를 가진 예약이 존재하지 않으면 거짓을 반환한다.") @Test - void should_get_reservation_times_when_date_and_theme_given() { - LocalDate date = LocalDate.of(2023, 8, 5); - List reservations = reservationDao.findByDateAndThemeId(date, 1); - assertThat(reservations).hasSize(1); - assertThat(reservations).containsExactly(new ReservationSavedDto(1, "브라운", date, 1L, 1L)); + void should_return_false_when_not_exist_date_and_timeId() { + boolean isExist = reservationDao.isExistByDateAndTimeId(LocalDate.of(2000, 1, 1), 999); + assertThat(isExist).isFalse(); } } diff --git a/src/test/java/roomescape/repository/ReservationTimeDaoTest.java b/src/test/java/roomescape/repository/ReservationTimeDaoTest.java index fe20fc8eb4..f158b27e55 100644 --- a/src/test/java/roomescape/repository/ReservationTimeDaoTest.java +++ b/src/test/java/roomescape/repository/ReservationTimeDaoTest.java @@ -15,81 +15,104 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) -@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) +@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) class ReservationTimeDaoTest { - @Autowired - private JdbcTemplate jdbcTemplate; + private static final int INITIAL_TIME_COUNT = 2; - @Autowired - private ReservationTimeDao reservationTimeDao; + private final JdbcTemplate jdbcTemplate; + private final ReservationTimeDao reservationTimeDao; + private final SimpleJdbcInsert timeInsertActor; - private SimpleJdbcInsert insertActor; + @Autowired + public ReservationTimeDaoTest(JdbcTemplate jdbcTemplate, ReservationTimeDao reservationTimeDao) { + this.jdbcTemplate = jdbcTemplate; + this.reservationTimeDao = reservationTimeDao; + this.timeInsertActor = new SimpleJdbcInsert(jdbcTemplate) + .withTableName("reservation_time") + .usingGeneratedKeyColumns("id"); + } @BeforeEach void setUp() { - jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY FALSE"); - jdbcTemplate.execute("TRUNCATE TABLE reservation_time RESTART IDENTITY"); - jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY TRUE"); + initDatabase(); + insertReservationTime("1:00"); + insertReservationTime("2:00"); + } - insertActor = new SimpleJdbcInsert(jdbcTemplate) - .withTableName("reservation_time") - .usingGeneratedKeyColumns("id"); - insertToReservationTime("10:00"); - insertToReservationTime("11:00"); + private void initDatabase() { + jdbcTemplate.execute("ALTER TABLE reservation_time SET REFERENTIAL_INTEGRITY FALSE"); + jdbcTemplate.execute("TRUNCATE TABLE reservation_time RESTART IDENTITY"); } - private void insertToReservationTime(String startAt) { + private void insertReservationTime(String startAt) { Map parameters = new HashMap<>(1); parameters.put("start_at", startAt); - insertActor.execute(parameters); + timeInsertActor.execute(parameters); } - @DisplayName("모든 예약 시간을 조회한다") + @DisplayName("예약 시간을 저장한다.") @Test - void should_get_reservation_times() { + void should_save_reservation_time() { + ReservationTime time = new ReservationTime(LocalTime.of(3, 0)); + reservationTimeDao.save(time); + assertThat(reservationTimeDao.findAll()).hasSize(INITIAL_TIME_COUNT + 1); + } + + @DisplayName("모든 예약 시간을 조회한다.") + @Test + void should_find_all_reservation_times() { List reservationTimes = reservationTimeDao.findAll(); - assertThat(reservationTimes).hasSize(2); + assertThat(reservationTimes).hasSize(INITIAL_TIME_COUNT); } - @DisplayName("예약 시간을 추가한다") + @DisplayName("특정 id의 예약 시간을 조회한다.") @Test - void should_add_reservation_time() { - reservationTimeDao.save(new ReservationTime(LocalTime.of(12, 0))); - Integer count = jdbcTemplate.queryForObject("select count(1) from reservation_time", Integer.class); - assertThat(count).isEqualTo(3); + void should_find_reservation_time_by_id() { + Optional actual = reservationTimeDao.findById(1); + + ReservationTime expected = new ReservationTime(1, LocalTime.of(1, 0)); + assertThat(actual).isNotEmpty(); + assertThat(actual).hasValue(expected); } - @DisplayName("예약 시간을 삭제한다") + @DisplayName("예약 시간을 삭제한다.") @Test void should_delete_reservation_time() { reservationTimeDao.deleteById(1); - Integer count = jdbcTemplate.queryForObject("select count(1) from reservation_time", Integer.class); - assertThat(count).isEqualTo(1); + assertThat(reservationTimeDao.findAll()).hasSize(INITIAL_TIME_COUNT - 1); } - @DisplayName("아이디에 해당하는 예약 시간을 조회한다.") + @DisplayName("특정 id의 예약 시간이 존재하는 경우 참을 반환한다.") @Test - void should_get_reservation_time() { - ReservationTime reservationTime = reservationTimeDao.findById(1).orElse(null); - assertThat(reservationTime.getStartAt()).isEqualTo(LocalTime.of(10, 0)); + void should_return_true_when_exist_id() { + Boolean isExist = reservationTimeDao.isExistById(1); + assertThat(isExist).isTrue(); } - @DisplayName("특정 id를 갖는 데이터가 존재하는 경우 참을 반환한다.") + @DisplayName("특정 id의 예약 시간이 존재하지 않는 경우 거짓을 반환한다.") @Test - void should_return_true_when_exist() { - Boolean isExist = reservationTimeDao.isExistById(1); + void should_return_false_when_not_exist_id() { + Boolean isExist = reservationTimeDao.isExistById(999); + assertThat(isExist).isFalse(); + } + + @DisplayName("특정 startAt의 예약 시간이 존재하는 경우 참을 반환한다.") + @Test + void should_return_true_when_exist_startAt() { + Boolean isExist = reservationTimeDao.isExistByStartAt(LocalTime.of(1, 0)); assertThat(isExist).isTrue(); } - @DisplayName("특정 id를 갖는 데이터가 존재하지 않는 경우 거짓을 반환한다.") + @DisplayName("특정 startAt의 예약 시간이 존재하지 않는 경우 거짓을 반환한다.") @Test - void should_return_false_when_not_exist() { - Boolean isExist = reservationTimeDao.isExistById(100000000); + void should_return_false_when_not_exist_startAt() { + Boolean isExist = reservationTimeDao.isExistByStartAt(LocalTime.of(9, 0)); assertThat(isExist).isFalse(); } } diff --git a/src/test/java/roomescape/repository/ThemeDaoTest.java b/src/test/java/roomescape/repository/ThemeDaoTest.java index 182ded9137..1f27953ee7 100644 --- a/src/test/java/roomescape/repository/ThemeDaoTest.java +++ b/src/test/java/roomescape/repository/ThemeDaoTest.java @@ -14,39 +14,39 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) -@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) +@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) // TODO: vs BEFORE_EACH class ThemeDaoTest { - @Autowired - private JdbcTemplate jdbcTemplate; + private static final int INITIAL_THEME_COUNT = 2; - @Autowired - private ThemeDao themeDao; + private final JdbcTemplate jdbcTemplate; + private final ThemeDao themeDao; + private final SimpleJdbcInsert themeInsertActor; - private SimpleJdbcInsert themeInsertActor; - private SimpleJdbcInsert reservationInsertActor; - private SimpleJdbcInsert timeInsertActor; + @Autowired + public ThemeDaoTest(JdbcTemplate jdbcTemplate, ThemeDao themeDao) { + this.jdbcTemplate = jdbcTemplate; + this.themeDao = themeDao; + this.themeInsertActor = new SimpleJdbcInsert(jdbcTemplate) + .withTableName("theme") + .usingGeneratedKeyColumns("id"); + } @BeforeEach void setUp() { - jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY FALSE"); + initDatabase(); + insertTheme("n1", "d1", "t1"); + insertTheme("n2", "d2", "t2"); + } + + private void initDatabase() { + jdbcTemplate.execute("ALTER TABLE theme SET REFERENTIAL_INTEGRITY FALSE"); jdbcTemplate.execute("TRUNCATE TABLE theme RESTART IDENTITY"); - jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY TRUE"); - themeInsertActor = new SimpleJdbcInsert(jdbcTemplate) - .withTableName("theme") - .usingGeneratedKeyColumns("id"); - reservationInsertActor = new SimpleJdbcInsert(jdbcTemplate) - .withTableName("reservation") - .usingGeneratedKeyColumns("id"); - timeInsertActor = new SimpleJdbcInsert(jdbcTemplate) - .withTableName("reservation_time") - .usingGeneratedKeyColumns("id"); - insertTheme("에버", "공포", "공포.jpg"); - insertTheme("배키", "미스터리", "미스터리.jpg"); } private void insertTheme(String name, String description, String thumbnail) { @@ -57,79 +57,33 @@ private void insertTheme(String name, String description, String thumbnail) { themeInsertActor.execute(parameters); } + @DisplayName("테마를 저장한다.") + @Test + void should_save_theme() { + Theme theme = new Theme("n3", "d3", "t3"); + themeDao.save(theme); + assertThat(themeDao.findAll()).hasSize(INITIAL_THEME_COUNT + 1); + } + @DisplayName("모든 테마를 조회한다.") @Test void should_find_all_themes() { List allThemes = themeDao.findAll(); - assertThat(allThemes).hasSize(2); + assertThat(allThemes).hasSize(INITIAL_THEME_COUNT); } - @DisplayName("테마를 저장한다.") + @DisplayName("특정 id의 테마를 조회한다.") @Test - void should_add_theme() { - Theme theme = new Theme("브라운", "공포", "공포.jpg"); - themeDao.save(theme); - assertThat(themeDao.findAll()).hasSize(3); + void should_find_theme_by_id() { + Optional theme = themeDao.findById(1); + assertThat(theme).isNotEmpty(); + assertThat(theme).hasValue(new Theme(1, "n1", "d1", "t1")); } @DisplayName("테마를 삭제한다.") @Test void should_delete_theme() { themeDao.deleteById(1); - assertThat(themeDao.findAll()).hasSize(1); - } - - /* - @DisplayName("특정 기간의 테마를 인기순으로 정렬하여 조회한다.") - @Test - void should_find_ranking_theme_by_date() { - jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY FALSE"); - jdbcTemplate.execute("TRUNCATE TABLE theme RESTART IDENTITY"); - jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY TRUE"); - insertReservationTime(LocalTime.of(10, 0)); - for (int i = 1; i <= 15; i++) { - insertTheme("name" + i, "description" + i, "thumbnail" + i); - } - for (int i = 1; i <= 10; i++) { - insertReservation("name" + i, LocalDate.of(2030, 1, i % 7 + 1), 1L, i); - } - insertReservation("name11", LocalDate.of(2030, 1, 1), 1L, 10); - insertReservation("name12", LocalDate.of(2030, 1, 2), 1L, 10); - insertReservation("name13", LocalDate.of(2030, 1, 3), 1L, 10); - insertReservation("name14", LocalDate.of(2030, 1, 4), 1L, 9); - insertReservation("name15", LocalDate.of(2030, 1, 5), 1L, 9); - - LocalDate before = LocalDate.of(2030, 1, 1); - LocalDate after = LocalDate.of(2030, 1, 7); - List themes = themeDao.findThemeRankingByDate(before, after, 10); - assertThat(themes).hasSize(10); - assertThat(themes).containsExactly( - new Theme(10, "name10", "description10", "thumbnail10"), - new Theme(9, "name9", "description9", "thumbnail9"), - new Theme(1, "name1", "description1", "thumbnail1"), - new Theme(2, "name2", "description2", "thumbnail2"), - new Theme(3, "name3", "description3", "thumbnail3"), - new Theme(4, "name4", "description4", "thumbnail4"), - new Theme(5, "name5", "description5", "thumbnail5"), - new Theme(6, "name6", "description6", "thumbnail6"), - new Theme(7, "name7", "description7", "thumbnail7"), - new Theme(8, "name8", "description8", "thumbnail8") - ); - } - - private void insertReservationTime(LocalTime startAt) { - Map parameters = new HashMap<>(1); - parameters.put("start_at", startAt); - timeInsertActor.execute(parameters); - } - - private void insertReservation(String name, LocalDate date, long timeId, long themeId) { - Map parameters = new HashMap<>(4); - parameters.put("name", name); - parameters.put("date", date); - parameters.put("time_id", timeId); - parameters.put("theme_id", themeId); - reservationInsertActor.execute(parameters); + assertThat(themeDao.findAll()).hasSize(INITIAL_THEME_COUNT - 1); } - */ } diff --git a/src/test/java/roomescape/service/FakeReservationDao.java b/src/test/java/roomescape/service/FakeReservationDao.java index db7528da37..afc2ebaafb 100644 --- a/src/test/java/roomescape/service/FakeReservationDao.java +++ b/src/test/java/roomescape/service/FakeReservationDao.java @@ -57,7 +57,7 @@ public List findByDateAndThemeId(LocalDate date, long theme } @Override - public List findByDateAndGroupByThemeIdAndOrderByCountAndLimit(LocalDate startDate, LocalDate endDate, int limit) { + public List findThemeIdByDateAndOrderByThemeIdCountAndLimit(LocalDate startDate, LocalDate endDate, int limit) { // Filter reservations by date List filteredReservations = reservations.stream() .filter(reservation -> reservation.getDate().isAfter(startDate) && reservation.getDate().isBefore(endDate)) From a3a52dd08d733bba4c46f2473e9788fa30af16f1 Mon Sep 17 00:00:00 2001 From: SCY Date: Sun, 5 May 2024 20:19:28 +0900 Subject: [PATCH 52/74] =?UTF-8?q?test(repositoryTest):=20=EB=A0=88?= =?UTF-8?q?=ED=8F=AC=EC=A7=80=ED=86=A0=EB=A6=AC=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/roomescape/model/Reservation.java | 14 ++ .../repository/ReservationDaoTest.java | 6 +- .../repository/ReservationRepositoryTest.java | 173 ++++++++++++++++++ .../ReservationTimeRepositoryTest.java | 167 +++++++++++++++++ .../repository/ThemeRepositoryTest.java | 126 +++++++++++++ 5 files changed, 483 insertions(+), 3 deletions(-) create mode 100644 src/test/java/roomescape/repository/ReservationRepositoryTest.java create mode 100644 src/test/java/roomescape/repository/ReservationTimeRepositoryTest.java create mode 100644 src/test/java/roomescape/repository/ThemeRepositoryTest.java diff --git a/src/main/java/roomescape/model/Reservation.java b/src/main/java/roomescape/model/Reservation.java index 75d415fe03..4afe13c038 100644 --- a/src/main/java/roomescape/model/Reservation.java +++ b/src/main/java/roomescape/model/Reservation.java @@ -1,6 +1,7 @@ package roomescape.model; import java.time.LocalDate; +import java.util.Objects; public class Reservation { @@ -47,4 +48,17 @@ public ReservationTime getTime() { public Theme getTheme() { return theme; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Reservation that = (Reservation) o; + return id == that.id && Objects.equals(name, that.name) && Objects.equals(date, that.date) && Objects.equals(time, that.time) && Objects.equals(theme, that.theme); + } + + @Override + public int hashCode() { + return Objects.hash(id, name, date, time, theme); + } } diff --git a/src/test/java/roomescape/repository/ReservationDaoTest.java b/src/test/java/roomescape/repository/ReservationDaoTest.java index 07c04945b7..ac65f40ddd 100644 --- a/src/test/java/roomescape/repository/ReservationDaoTest.java +++ b/src/test/java/roomescape/repository/ReservationDaoTest.java @@ -75,7 +75,7 @@ private void insertReservationTime(String startAt) { } private void insertReservation(String name, String date, long timeId, long themeId) { - Map parameters = new HashMap<>(3); + Map parameters = new HashMap<>(4); parameters.put("name", name); parameters.put("date", date); parameters.put("time_id", timeId); @@ -112,7 +112,7 @@ void should_find_all_reservations() { @DisplayName("특정 id의 예약을 조회한다.") @Test - void should_find_reservation_by_id() { + void should_find_reservation_by_id() { // TODO: test empty optional ReservationSavedDto expected = new ReservationSavedDto(1, "n1", LocalDate.of(2000, 1, 1), 1L, 1L); Optional actual = reservationDao.findById(1); @@ -136,7 +136,7 @@ void should_find_reservation_by_date_and_themeId() { void should_find_themeId_between_date_and_order_by_themeId_count_and_limit() { List themeIds = reservationDao.findThemeIdByDateAndOrderByThemeIdCountAndLimit( LocalDate.of(2000, 1, 1), LocalDate.of(2000, 1, 2), 10); - + assertThat(themeIds).hasSizeLessThanOrEqualTo(10); assertThat(themeIds).containsExactly(1L, 2L); } diff --git a/src/test/java/roomescape/repository/ReservationRepositoryTest.java b/src/test/java/roomescape/repository/ReservationRepositoryTest.java new file mode 100644 index 0000000000..905303863c --- /dev/null +++ b/src/test/java/roomescape/repository/ReservationRepositoryTest.java @@ -0,0 +1,173 @@ +package roomescape.repository; + +import org.junit.jupiter.api.BeforeEach; +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.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.simple.SimpleJdbcInsert; +import org.springframework.test.annotation.DirtiesContext; +import roomescape.model.Reservation; +import roomescape.model.ReservationTime; +import roomescape.model.Theme; + +import java.time.LocalDate; +import java.time.LocalTime; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) +@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) +class ReservationRepositoryTest { + + private static final int INITIAL_RESERVATION_COUNT = 2; + + private final JdbcTemplate jdbcTemplate; + private final ReservationRepository reservationRepository; + private final SimpleJdbcInsert themeInsertActor; + private final SimpleJdbcInsert timeInsertActor; + private final SimpleJdbcInsert reservationInsertActor; + + @Autowired + public ReservationRepositoryTest(JdbcTemplate jdbcTemplate, ReservationRepository reservationRepository) { + this.jdbcTemplate = jdbcTemplate; + this.reservationRepository = reservationRepository; + this.themeInsertActor = new SimpleJdbcInsert(jdbcTemplate) + .withTableName("theme") + .usingGeneratedKeyColumns("id"); + this.timeInsertActor = new SimpleJdbcInsert(jdbcTemplate) + .withTableName("reservation_time") + .usingGeneratedKeyColumns("id"); + this.reservationInsertActor = new SimpleJdbcInsert(jdbcTemplate) + .withTableName("reservation") + .usingGeneratedKeyColumns("id"); + } + + @BeforeEach + void setUp() { + initDatabase(); + insertTheme("n1", "d1", "t1"); + insertTheme("n2", "d2", "t2"); + insertReservationTime("1:00"); + insertReservationTime("2:00"); + insertReservation("n1", "2000-01-01", 1, 1); + insertReservation("n2", "2000-01-02", 2, 2); + } + + private void initDatabase() { + jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY FALSE"); + jdbcTemplate.execute("TRUNCATE TABLE theme RESTART IDENTITY"); + jdbcTemplate.execute("TRUNCATE TABLE reservation_time RESTART IDENTITY"); + jdbcTemplate.execute("TRUNCATE TABLE reservation RESTART IDENTITY"); + } + + private void insertTheme(String name, String description, String thumbnail) { + Map parameters = new HashMap<>(3); + parameters.put("name", name); + parameters.put("description", description); + parameters.put("thumbnail", thumbnail); + themeInsertActor.execute(parameters); + } + + private void insertReservationTime(String startAt) { + Map parameters = new HashMap<>(1); + parameters.put("start_at", startAt); + timeInsertActor.execute(parameters); + } + + private void insertReservation(String name, String date, long timeId, long themeId) { + Map parameters = new HashMap<>(4); + parameters.put("name", name); + parameters.put("date", date); + parameters.put("time_id", timeId); + parameters.put("theme_id", themeId); + reservationInsertActor.execute(parameters); + } + + @DisplayName("모든 예약을 조회한다.") + @Test + void should_find_all_reservations() { + List reservations = reservationRepository.findAllReservations(); + assertThat(reservations).hasSize(INITIAL_RESERVATION_COUNT); + } + + @DisplayName("특정 id를 가진 예약 시간을 조회한다.") + @Test + void should_find_reservation_time_by_id() { + Optional time = reservationRepository.findReservationTimeById(1); + assertThat(time).hasValue(new ReservationTime(1, LocalTime.of(1, 0))); + } + + @DisplayName("특정 id를 가진 테마를 조회한다.") + @Test + void should_find_theme_by_id() { + Optional time = reservationRepository.findThemeById(1); + assertThat(time).hasValue(new Theme(1, "n1", "d1", "t1")); + } + + @DisplayName("특정 날짜와 시간을 가진 예약이 존재하는 경우 참을 반환한다.") + @Test + void should_return_true_when_exist_reservation_by_date_and_timeId() { + boolean isExist = reservationRepository.isExistReservationByDateAndTimeId(LocalDate.of(2000, 1, 1), 1); + assertThat(isExist).isTrue(); + } + + @DisplayName("특정 날짜와 시간을 가진 예약이 존재하지 않는 경우 거짓을 반환한다.") + @Test + void should_return_false_when_not_exist_reservation_by_date_and_timeId() { + boolean isExist = reservationRepository.isExistReservationByDateAndTimeId(LocalDate.of(9999, 1, 1), 1); + assertThat(isExist).isFalse(); + } + + @DisplayName("예약을 저장한 후 저장된 예약을 반환한다.") + @Test + void should_save_reservation() { + ReservationTime time = new ReservationTime(1, LocalTime.of(1, 0)); + Theme theme = new Theme(1, "n1", "d1", "t1"); + Reservation before = new Reservation("n3", LocalDate.of(2000, 1, 3), time, theme); + Reservation actual = reservationRepository.saveReservation(before); + + Reservation after = new Reservation(3, "n3", LocalDate.of(2000, 1, 3), time, theme); + assertThat(actual).isEqualTo(after); + } + + @DisplayName("특정 id를 가진 예약이 존재하는 경우 참을 반환한다.") + @Test + void should_return_true_when_exist_reservation_by_id() { + boolean isExist = reservationRepository.isExistReservationById(1); + assertThat(isExist).isTrue(); + } + + @DisplayName("특정 id를 가진 예약이 존재하지 않는 경우 거짓을 반환한다.") + @Test + void should_return_false_when_not_exist_reservation_by_id() { + boolean isExist = reservationRepository.isExistReservationById(999); + assertThat(isExist).isFalse(); + } + + @DisplayName("예약을 삭제한다.") + @Test + void should_delete_reservation() { + reservationRepository.deleteReservationById(1); + assertThat(reservationRepository.findAllReservations()).hasSize(INITIAL_RESERVATION_COUNT - 1); + } + + @DisplayName("특정 날짜와 테마의 예약된 시간을 조회한다.") + @Test + void should_find_booked_reservation_time() { // TODO: test case 구체화 + List bookedTimes = reservationRepository.findReservationTimeBooked(LocalDate.of(2000, 1, 1), 1); + assertThat(bookedTimes).containsExactly(new ReservationTime(1, LocalTime.of(1, 0))); + } + + @DisplayName("특정 날짜와 테마의 예약되지 않은 시간을 조회한다.") + @Test + void should_find_not_booked_reservation_time() { // TODO: test case 구체화 + List notBookedTimes = reservationRepository.findReservationTimeNotBooked(LocalDate.of(2000, 1, 1), 1); + assertThat(notBookedTimes).containsExactly(new ReservationTime(2, LocalTime.of(2, 0))); + } +} \ No newline at end of file diff --git a/src/test/java/roomescape/repository/ReservationTimeRepositoryTest.java b/src/test/java/roomescape/repository/ReservationTimeRepositoryTest.java new file mode 100644 index 0000000000..aa1bc914fa --- /dev/null +++ b/src/test/java/roomescape/repository/ReservationTimeRepositoryTest.java @@ -0,0 +1,167 @@ +package roomescape.repository; + +import org.junit.jupiter.api.BeforeEach; +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.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.simple.SimpleJdbcInsert; +import org.springframework.test.annotation.DirtiesContext; +import roomescape.model.ReservationTime; + +import java.time.LocalTime; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) +@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) +public class ReservationTimeRepositoryTest { + + private static final int INITIAL_TIME_COUNT = 2; + + private final JdbcTemplate jdbcTemplate; + private final ReservationTimeRepository reservationTimeRepository; + private final SimpleJdbcInsert themeInsertActor; + private final SimpleJdbcInsert timeInsertActor; + private final SimpleJdbcInsert reservationInsertActor; + + @Autowired + public ReservationTimeRepositoryTest(JdbcTemplate jdbcTemplate, ReservationTimeRepository reservationTimeRepository) { + this.jdbcTemplate = jdbcTemplate; + this.reservationTimeRepository = reservationTimeRepository; + this.themeInsertActor = new SimpleJdbcInsert(jdbcTemplate) + .withTableName("theme") + .usingGeneratedKeyColumns("id"); + this.timeInsertActor = new SimpleJdbcInsert(jdbcTemplate) + .withTableName("reservation_time") + .usingGeneratedKeyColumns("id"); + this.reservationInsertActor = new SimpleJdbcInsert(jdbcTemplate) + .withTableName("reservation") + .usingGeneratedKeyColumns("id"); + } + + @BeforeEach + void setUp() { + initDatabase(); + insertTheme("n1", "d1", "t1"); + insertTheme("n2", "d2", "t2"); + insertReservationTime("1:00"); + insertReservationTime("2:00"); + insertReservation("n1", "2000-01-01", 1, 1); + insertReservation("n2", "2000-01-02", 2, 2); + } + + private void initDatabase() { + jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY FALSE"); + jdbcTemplate.execute("TRUNCATE TABLE theme RESTART IDENTITY"); + jdbcTemplate.execute("TRUNCATE TABLE reservation_time RESTART IDENTITY"); + jdbcTemplate.execute("TRUNCATE TABLE reservation RESTART IDENTITY"); + } + + private void insertTheme(String name, String description, String thumbnail) { + Map parameters = new HashMap<>(3); + parameters.put("name", name); + parameters.put("description", description); + parameters.put("thumbnail", thumbnail); + themeInsertActor.execute(parameters); + } + + private void insertReservationTime(String startAt) { + Map parameters = new HashMap<>(1); + parameters.put("start_at", startAt); + timeInsertActor.execute(parameters); + } + + private void insertReservation(String name, String date, long timeId, long themeId) { + Map parameters = new HashMap<>(4); + parameters.put("name", name); + parameters.put("date", date); + parameters.put("time_id", timeId); + parameters.put("theme_id", themeId); + reservationInsertActor.execute(parameters); + } + + @DisplayName("모든 예약 시간을 조회한다.") + @Test + void should_find_all_reservation_times() { + List times = reservationTimeRepository.findAllReservationTimes(); + assertThat(times).hasSize(INITIAL_TIME_COUNT); + } + + @DisplayName("특정 id의 예약 시간을 조회한다.") + @Test + void should_find_reservation_time_by_id() { + ReservationTime expected = new ReservationTime(1, LocalTime.of(1, 0)); + + Optional actual = reservationTimeRepository.findReservationById(1); + + assertThat(actual).isNotEmpty(); + assertThat(actual).hasValue(expected); + } + + @DisplayName("예약 시간을 저장한 후 저장된 시간을 반환한다.") + @Test + void should_save_reservation_time() { + ReservationTime before = new ReservationTime(LocalTime.of(3, 0)); + + Optional actual = reservationTimeRepository.saveReservationTime(before); + + ReservationTime after = new ReservationTime(3, LocalTime.of(3, 0)); + assertThat(actual).isNotEmpty(); + assertThat(actual).hasValue(after); + } + + @DisplayName("예약 시간을 삭제한다.") + @Test + void should_delete_reservation_time() { + reservationTimeRepository.deleteReservationTimeById(1); + assertThat(reservationTimeRepository.findAllReservationTimes()).hasSize(INITIAL_TIME_COUNT - 1); + } + + @DisplayName("특정 id를 가진 예약 시간이 존재하는 경우 참을 반환한다.") + @Test + void should_return_true_when_exist_id() { + boolean isExist = reservationTimeRepository.isExistReservationTimeById(1); + assertThat(isExist).isTrue(); + } + + @DisplayName("특정 id를 가진 예약 시간이 존재하지 않는 경우 거짓을 반환한다.") + @Test + void should_return_false_when_not_exist_id() { + boolean isExist = reservationTimeRepository.isExistReservationTimeById(999); + assertThat(isExist).isFalse(); + } + + @DisplayName("특정 startAt을 가진 예약 시간이 존재하는 경우 참을 반환한다.") + @Test + void should_return_true_when_exist_startAt() { + boolean isExist = reservationTimeRepository.isExistReservationTimeByStartAt(LocalTime.of(1, 0)); + assertThat(isExist).isTrue(); + } + + @DisplayName("특정 startAt을 가진 예약 시간이 존재하지 않는 경우 거짓을 반환한다.") + @Test + void should_return_false_when_not_exist_startAt() { + boolean isExist = reservationTimeRepository.isExistReservationTimeByStartAt(LocalTime.of(9, 0)); + assertThat(isExist).isFalse(); + } + + @DisplayName("특정 time_id를 가진 예약 시간이 존재하는 경우 참을 반환한다.") + @Test + void should_return_true_when_exist_timeId() { + boolean isExist = reservationTimeRepository.isExistReservationByTimeId(1); + assertThat(isExist).isTrue(); + } + + @DisplayName("특정 time_id를 가진 예약 시간이 존재하지 않는 경우 거짓을 반환한다.") + @Test + void should_return_false_when_not_exist_timeId() { + boolean isExist = reservationTimeRepository.isExistReservationByTimeId(999); + assertThat(isExist).isFalse(); + } +} diff --git a/src/test/java/roomescape/repository/ThemeRepositoryTest.java b/src/test/java/roomescape/repository/ThemeRepositoryTest.java new file mode 100644 index 0000000000..3b0e603171 --- /dev/null +++ b/src/test/java/roomescape/repository/ThemeRepositoryTest.java @@ -0,0 +1,126 @@ +package roomescape.repository; + +import org.junit.jupiter.api.BeforeEach; +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.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.simple.SimpleJdbcInsert; +import org.springframework.test.annotation.DirtiesContext; +import roomescape.model.Theme; + +import java.time.LocalDate; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) +@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) +class ThemeRepositoryTest { + + private static final int INITIAL_THEME_COUNT = 2; + + private final JdbcTemplate jdbcTemplate; + private final ThemeRepository themeRepository; + private final SimpleJdbcInsert themeInsertActor; + private final SimpleJdbcInsert timeInsertActor; + private final SimpleJdbcInsert reservationInsertActor; + + @Autowired + public ThemeRepositoryTest(JdbcTemplate jdbcTemplate, ThemeRepository themeRepository) { + this.jdbcTemplate = jdbcTemplate; + this.themeRepository = themeRepository; + this.themeInsertActor = new SimpleJdbcInsert(jdbcTemplate) + .withTableName("theme") + .usingGeneratedKeyColumns("id"); + this.timeInsertActor = new SimpleJdbcInsert(jdbcTemplate) + .withTableName("reservation_time") + .usingGeneratedKeyColumns("id"); + this.reservationInsertActor = new SimpleJdbcInsert(jdbcTemplate) + .withTableName("reservation") + .usingGeneratedKeyColumns("id"); + } + + @BeforeEach + void setUp() { + initDatabase(); + insertTheme("n1", "d1", "t1"); + insertTheme("n2", "d2", "t2"); + insertReservationTime("1:00"); + insertReservationTime("2:00"); + insertReservation("n1", "2000-01-01", 1, 1); + insertReservation("n2", "2000-01-02", 2, 2); + } + + private void initDatabase() { + jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY FALSE"); + jdbcTemplate.execute("TRUNCATE TABLE theme RESTART IDENTITY"); + jdbcTemplate.execute("TRUNCATE TABLE reservation_time RESTART IDENTITY"); + jdbcTemplate.execute("TRUNCATE TABLE reservation RESTART IDENTITY"); + } + + private void insertTheme(String name, String description, String thumbnail) { + Map parameters = new HashMap<>(3); + parameters.put("name", name); + parameters.put("description", description); + parameters.put("thumbnail", thumbnail); + themeInsertActor.execute(parameters); + } + + private void insertReservationTime(String startAt) { + Map parameters = new HashMap<>(1); + parameters.put("start_at", startAt); + timeInsertActor.execute(parameters); + } + + private void insertReservation(String name, String date, long timeId, long themeId) { + Map parameters = new HashMap<>(4); + parameters.put("name", name); + parameters.put("date", date); + parameters.put("time_id", timeId); + parameters.put("theme_id", themeId); + reservationInsertActor.execute(parameters); + } + + @DisplayName("모든 테마를 조회한다.") + @Test + void should_find_all_themes() { + List themes = themeRepository.findAllThemes(); + assertThat(themes).hasSize(2); + } + + @DisplayName("테마를 저장한 후 저장된 테마를 반환한다.") + @Test + void should_save_theme_and_return() { + Theme before = new Theme("n3", "d3", "t3"); + + Optional actual = themeRepository.saveTheme(before); + + Theme after = new Theme(3, "n3", "d3", "t3"); + assertThat(actual).isNotEmpty(); + assertThat(actual).hasValue(after); + } + + @DisplayName("테마를 삭제한다.") + @Test + void should_delete_theme_by_id() { + themeRepository.deleteThemeById(1); + assertThat(themeRepository.findAllThemes()).hasSize(INITIAL_THEME_COUNT - 1); + } + + @DisplayName("두 날짜 사이의 예약을 테마의 개수로 내림차순 정렬하여, 특정 개수의 테마를 조회한다.") + @Test + void should_find_theme_ranking_by_date() { + List themes = themeRepository.findThemeRankingByDate( + LocalDate.of(2000, 1, 1), LocalDate.of(2000, 1, 2), 10); + assertThat(themes).hasSizeLessThanOrEqualTo(10); + assertThat(themes).containsExactly( + new Theme(1, "n1", "d1", "t1"), + new Theme(2, "n2", "d2", "t2") + ); + } +} \ No newline at end of file From 7785cd14755d84c6e5fd47fc541f85c5d5a9bdbc Mon Sep 17 00:00:00 2001 From: SCY Date: Sun, 5 May 2024 20:20:02 +0900 Subject: [PATCH 53/74] =?UTF-8?q?chore(daoTest):=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EB=82=B4=20=ED=8C=A8=ED=82=A4=EC=A7=80=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dao/DatabaseConnectionTest.java} | 4 ++-- .../roomescape/repository/{ => dao}/ReservationDaoTest.java | 3 +-- .../repository/{ => dao}/ReservationTimeDaoTest.java | 3 +-- .../java/roomescape/repository/{ => dao}/ThemeDaoTest.java | 3 +-- 4 files changed, 5 insertions(+), 8 deletions(-) rename src/test/java/roomescape/{dao/DBConnectionTest.java => repository/dao/DatabaseConnectionTest.java} (96%) rename src/test/java/roomescape/repository/{ => dao}/ReservationDaoTest.java (98%) rename src/test/java/roomescape/repository/{ => dao}/ReservationTimeDaoTest.java (98%) rename src/test/java/roomescape/repository/{ => dao}/ThemeDaoTest.java (97%) diff --git a/src/test/java/roomescape/dao/DBConnectionTest.java b/src/test/java/roomescape/repository/dao/DatabaseConnectionTest.java similarity index 96% rename from src/test/java/roomescape/dao/DBConnectionTest.java rename to src/test/java/roomescape/repository/dao/DatabaseConnectionTest.java index e63620e849..1303da6572 100644 --- a/src/test/java/roomescape/dao/DBConnectionTest.java +++ b/src/test/java/roomescape/repository/dao/DatabaseConnectionTest.java @@ -1,4 +1,4 @@ -package roomescape.dao; +package roomescape.repository.dao; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -14,7 +14,7 @@ @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) -class DBConnectionTest { +class DatabaseConnectionTest { @Autowired private JdbcTemplate jdbcTemplate; diff --git a/src/test/java/roomescape/repository/ReservationDaoTest.java b/src/test/java/roomescape/repository/dao/ReservationDaoTest.java similarity index 98% rename from src/test/java/roomescape/repository/ReservationDaoTest.java rename to src/test/java/roomescape/repository/dao/ReservationDaoTest.java index ac65f40ddd..75d1d55d56 100644 --- a/src/test/java/roomescape/repository/ReservationDaoTest.java +++ b/src/test/java/roomescape/repository/dao/ReservationDaoTest.java @@ -1,4 +1,4 @@ -package roomescape.repository; +package roomescape.repository.dao; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -11,7 +11,6 @@ import roomescape.model.Reservation; import roomescape.model.ReservationTime; import roomescape.model.Theme; -import roomescape.repository.dao.ReservationDao; import roomescape.repository.dto.ReservationSavedDto; import java.time.LocalDate; diff --git a/src/test/java/roomescape/repository/ReservationTimeDaoTest.java b/src/test/java/roomescape/repository/dao/ReservationTimeDaoTest.java similarity index 98% rename from src/test/java/roomescape/repository/ReservationTimeDaoTest.java rename to src/test/java/roomescape/repository/dao/ReservationTimeDaoTest.java index f158b27e55..aaf617a287 100644 --- a/src/test/java/roomescape/repository/ReservationTimeDaoTest.java +++ b/src/test/java/roomescape/repository/dao/ReservationTimeDaoTest.java @@ -1,4 +1,4 @@ -package roomescape.repository; +package roomescape.repository.dao; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -9,7 +9,6 @@ import org.springframework.jdbc.core.simple.SimpleJdbcInsert; import org.springframework.test.annotation.DirtiesContext; import roomescape.model.ReservationTime; -import roomescape.repository.dao.ReservationTimeDao; import java.time.LocalTime; import java.util.HashMap; diff --git a/src/test/java/roomescape/repository/ThemeDaoTest.java b/src/test/java/roomescape/repository/dao/ThemeDaoTest.java similarity index 97% rename from src/test/java/roomescape/repository/ThemeDaoTest.java rename to src/test/java/roomescape/repository/dao/ThemeDaoTest.java index 1f27953ee7..00b57b8c3b 100644 --- a/src/test/java/roomescape/repository/ThemeDaoTest.java +++ b/src/test/java/roomescape/repository/dao/ThemeDaoTest.java @@ -1,4 +1,4 @@ -package roomescape.repository; +package roomescape.repository.dao; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -9,7 +9,6 @@ import org.springframework.jdbc.core.simple.SimpleJdbcInsert; import org.springframework.test.annotation.DirtiesContext; import roomescape.model.Theme; -import roomescape.repository.dao.ThemeDao; import java.util.HashMap; import java.util.List; From e30d98760fc22e9a24b5ff8c3a53dd910499394e Mon Sep 17 00:00:00 2001 From: SCY Date: Sun, 5 May 2024 21:13:18 +0900 Subject: [PATCH 54/74] =?UTF-8?q?refactor(serviceTest):=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=BB=A8=EB=B2=A4=EC=85=98=20=ED=86=B5?= =?UTF-8?q?=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/ReservationService.java | 9 +- .../service/ReservationServiceTest.java | 108 +++++++++--------- .../service/ReservationTimeServiceTest.java | 76 ++++++------ .../roomescape/service/ThemeServiceTest.java | 39 ++++--- .../{ => fakedao}/FakeReservationDao.java | 15 +-- .../{ => fakedao}/FakeReservationTimeDao.java | 4 +- .../service/{ => fakedao}/FakeThemeDao.java | 2 +- 7 files changed, 128 insertions(+), 125 deletions(-) rename src/test/java/roomescape/service/{ => fakedao}/FakeReservationDao.java (90%) rename src/test/java/roomescape/service/{ => fakedao}/FakeReservationTimeDao.java (94%) rename src/test/java/roomescape/service/{ => fakedao}/FakeThemeDao.java (97%) diff --git a/src/main/java/roomescape/service/ReservationService.java b/src/main/java/roomescape/service/ReservationService.java index 5c67e023de..4147d12119 100644 --- a/src/main/java/roomescape/service/ReservationService.java +++ b/src/main/java/roomescape/service/ReservationService.java @@ -13,6 +13,7 @@ import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.LocalTime; import java.time.temporal.ChronoUnit; import java.util.List; import java.util.stream.Stream; @@ -46,13 +47,13 @@ public Reservation saveReservation(ReservationDto reservationDto) { } private void validate(LocalDate date, ReservationTime time) { - validateDateTime(date, time); + validateDateTime(date, time.getStartAt()); validateDuplication(date, time.getId()); } - private void validateDateTime(LocalDate date, ReservationTime time) { + private void validateDateTime(LocalDate date, LocalTime time) { LocalDateTime now = LocalDateTime.now().truncatedTo(ChronoUnit.SECONDS); - LocalDateTime dateTime = LocalDateTime.of(date, time.getStartAt()).truncatedTo(ChronoUnit.SECONDS); + LocalDateTime dateTime = LocalDateTime.of(date, time).truncatedTo(ChronoUnit.SECONDS); if (dateTime.isBefore(now)) { throw new BadRequestException("[ERROR] 현재 이전 예약은 할 수 없습니다."); } @@ -87,7 +88,7 @@ public List findReservationTimesInformation(Local private List mapToResponse(List times, boolean isBooked) { return times.stream() - .map(time -> new MemberReservationTimeResponse(time.getId(), time.getStartAt(), isBooked)) + .map(time -> new MemberReservationTimeResponse(time.getId(), time.getStartAt().truncatedTo(ChronoUnit.SECONDS), isBooked)) .toList(); } diff --git a/src/test/java/roomescape/service/ReservationServiceTest.java b/src/test/java/roomescape/service/ReservationServiceTest.java index 04697b912a..8627d7c669 100644 --- a/src/test/java/roomescape/service/ReservationServiceTest.java +++ b/src/test/java/roomescape/service/ReservationServiceTest.java @@ -16,9 +16,13 @@ import roomescape.repository.dao.ThemeDao; import roomescape.repository.dto.ReservationSavedDto; import roomescape.service.dto.ReservationDto; +import roomescape.service.fakedao.FakeReservationDao; +import roomescape.service.fakedao.FakeReservationTimeDao; +import roomescape.service.fakedao.FakeThemeDao; import java.time.LocalDate; import java.time.LocalTime; +import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.List; @@ -26,96 +30,95 @@ class ReservationServiceTest { + private static final int INITIAL_RESERVATION_COUNT = 3; + private static final int INITIAL_TIME_COUNT = 3; + private ReservationService reservationService; - private ReservationRepository reservationRepository; - private ReservationTimeDao reservationTimeDao; // TODO: remove field @BeforeEach - void setUp() { // 테케 의존성 분리하기 + void setUp() { ThemeDao themeDao = new FakeThemeDao(new ArrayList<>(List.of( - new Theme(1, "에버", "공포", "공포.jpg"), - new Theme(2, "배키", "미스터리", "미스터리.jpg"), - new Theme(3, "포비", "스릴러", "스릴러.jpg")))); - reservationTimeDao = new FakeReservationTimeDao(new ArrayList<>(List.of( - new ReservationTime(1, LocalTime.of(10, 0)), - new ReservationTime(2, LocalTime.of(11, 0))))); + new Theme(1, "n1", "d1", "t1"), + new Theme(2, "n2", "d2", "t2"), + new Theme(3, "n3", "d3", "t3")))); + ReservationTimeDao reservationTimeDao = new FakeReservationTimeDao(new ArrayList<>(List.of( + new ReservationTime(1, LocalTime.of(1, 0)), + new ReservationTime(2, LocalTime.of(2, 0)), + new ReservationTime(3, LocalTime.now())))); ReservationDao reservationDao = new FakeReservationDao(new ArrayList<>(List.of( - new ReservationSavedDto(1, "브라운", LocalDate.of(2030, 8, 5), 2L, 1L), - new ReservationSavedDto(1, "리사", LocalDate.of(2030, 8, 1), 2L, 2L)))); - reservationRepository = new ReservationRepository(reservationDao, reservationTimeDao, themeDao); - reservationService = new ReservationService(reservationRepository); + new ReservationSavedDto(1, "n1", LocalDate.of(2000, 1, 1), 1L, 1L), + new ReservationSavedDto(2, "n2", LocalDate.of(2000, 1, 2), 2L, 2L), + new ReservationSavedDto(3, "n3", LocalDate.of(9999, 9, 9), 1L, 1L)))); + reservationService = new ReservationService(new ReservationRepository(reservationDao, reservationTimeDao, themeDao)); } - @DisplayName("모든 예약 시간을 반환한다") + @DisplayName("모든 예약을 반환한다.") @Test - void should_return_all_reservation_times() { + void should_find_all_reservations() { List reservations = reservationService.findAllReservations(); - assertThat(reservations).hasSize(2); + assertThat(reservations).hasSize(INITIAL_RESERVATION_COUNT); } - @DisplayName("예약 시간을 추가한다") + @DisplayName("예약을 추가한다.") @Test - void should_add_reservation_times() { - reservationService.saveReservation( - new ReservationDto("네오", LocalDate.of(2030, 1, 1), 1L, 1L)); - List allReservations = reservationService.findAllReservations(); - assertThat(allReservations).hasSize(3); + void should_save_reservation() { + ReservationDto reservationDto = new ReservationDto("n", LocalDate.of(3333, 3, 3), 1L, 1L); + reservationService.saveReservation(reservationDto); + assertThat(reservationService.findAllReservations()).hasSize(INITIAL_RESERVATION_COUNT + 1); } - @DisplayName("예약 시간을 삭제한다") + @DisplayName("예약을 삭제한다.") @Test - void should_remove_reservation_times() { + void should_delete_reservation() { reservationService.deleteReservation(1); - List allReservations = reservationService.findAllReservations(); - assertThat(allReservations).hasSize(1); - } - - @DisplayName("존재하지 않는 예약을 삭제하면 예외가 발생한다.") - @Test - void should_throw_exception_when_not_exist_reservation_time() { - assertThatThrownBy(() -> reservationService.deleteReservation(100000000)) - .isInstanceOf(NotFoundException.class) - .hasMessage("[ERROR] 존재하지 않는 예약입니다."); + assertThat(reservationService.findAllReservations()).hasSize(INITIAL_RESERVATION_COUNT - 1); } - @DisplayName("존재하는 예약을 삭제하면 예외가 발생하지 않는다.") + @DisplayName("존재하는 예약을 삭제하려 하면 예외가 발생하지 않는다.") @Test void should_not_throw_exception_when_exist_reservation_time() { assertThatCode(() -> reservationService.deleteReservation(1)) .doesNotThrowAnyException(); } - @DisplayName("현재 이전으로 예약하면 예외가 발생한다.") + @DisplayName("존재하지 않는 예약을 삭제하려 하면 예외가 발생한다.") + @Test + void should_throw_exception_when_not_exist_reservation_time() { + assertThatThrownBy(() -> reservationService.deleteReservation(999)) + .isInstanceOf(NotFoundException.class) + .hasMessage("[ERROR] 존재하지 않는 예약입니다."); + } + + @DisplayName("현재 이전으로 예약하려 하면 예외가 발생한다.") @Test void should_throw_exception_when_previous_date() { - ReservationDto request = new ReservationDto("에버", LocalDate.of(2000, 1, 11), 1L, 1L); - assertThatThrownBy(() -> reservationService.saveReservation(request)) + ReservationDto reservationDto = new ReservationDto("n", LocalDate.of(999, 9, 9), 1L, 1L); + assertThatThrownBy(() -> reservationService.saveReservation(reservationDto)) .isInstanceOf(BadRequestException.class) .hasMessage("[ERROR] 현재 이전 예약은 할 수 없습니다."); } - @DisplayName("현재로 예약하면 예외가 발생하지 않는다.") + @DisplayName("현재(날짜+시간)로 예약하려 하면 예외가 발생하지 않는다.") @Test void should_not_throw_exception_when_current_date() { - long timeId = reservationTimeDao.save(new ReservationTime(3, LocalTime.now())); - ReservationDto request = new ReservationDto("에버", LocalDate.now(), timeId, 1L); - assertThatCode(() -> reservationService.saveReservation(request)) + ReservationDto reservationDto = new ReservationDto("n", LocalDate.now(), 3L, 1L); + assertThatCode(() -> reservationService.saveReservation(reservationDto)) .doesNotThrowAnyException(); } - @DisplayName("현재 이후로 예약하면 예외가 발생하지 않는다.") + @DisplayName("현재 이후로 예약하려 하면 예외가 발생하지 않는다.") @Test void should_not_throw_exception_when_later_date() { - ReservationDto request = new ReservationDto("에버", LocalDate.of(2030, 1, 11), 1L, 1L); - assertThatCode(() -> reservationService.saveReservation(request)) + ReservationDto reservationDto = new ReservationDto("n", LocalDate.of(3333, 12, 31), 1L, 1L); + assertThatCode(() -> reservationService.saveReservation(reservationDto)) .doesNotThrowAnyException(); } - @DisplayName("날짜, 시간이 일치하는 예약을 추가하려 할 때 예외가 발생한다.") + @DisplayName("날짜와 시간이 중복되는 예약을 추가하려 할 때 예외가 발생한다.") @Test void should_throw_exception_when_add_exist_reservation() { - ReservationDto request = new ReservationDto("배키", LocalDate.of(2030, 8, 5), 2L, 2L); - assertThatThrownBy(() -> reservationService.saveReservation(request)) + ReservationDto reservationDto = new ReservationDto("n", LocalDate.of(9999, 9, 9), 1L, 2L); + assertThatThrownBy(() -> reservationService.saveReservation(reservationDto)) .isInstanceOf(DuplicatedException.class) .hasMessage("[ERROR] 중복되는 예약은 추가할 수 없습니다."); } @@ -123,12 +126,13 @@ void should_throw_exception_when_add_exist_reservation() { @DisplayName("예약 가능 상태를 담은 시간 정보를 반환한다.") @Test void should_return_times_with_book_state() { - LocalDate date = LocalDate.of(2030, 8, 5); + LocalDate date = LocalDate.of(9999, 9, 9); List times = reservationService.findReservationTimesInformation(date, 1); - assertThat(times).hasSize(2); + assertThat(times).hasSize(INITIAL_TIME_COUNT); assertThat(times).containsOnly( - new MemberReservationTimeResponse(1, LocalTime.of(10, 0), false), - new MemberReservationTimeResponse(2, LocalTime.of(11, 0), true) + new MemberReservationTimeResponse(1, LocalTime.of(1, 0), true), + new MemberReservationTimeResponse(2, LocalTime.of(2, 0), false), + new MemberReservationTimeResponse(3, LocalTime.now().truncatedTo(ChronoUnit.SECONDS), false) ); } } diff --git a/src/test/java/roomescape/service/ReservationTimeServiceTest.java b/src/test/java/roomescape/service/ReservationTimeServiceTest.java index e6203b6573..9b0a061dad 100644 --- a/src/test/java/roomescape/service/ReservationTimeServiceTest.java +++ b/src/test/java/roomescape/service/ReservationTimeServiceTest.java @@ -12,6 +12,8 @@ import roomescape.repository.dao.ReservationTimeDao; import roomescape.repository.dto.ReservationSavedDto; import roomescape.service.dto.ReservationTimeDto; +import roomescape.service.fakedao.FakeReservationDao; +import roomescape.service.fakedao.FakeReservationTimeDao; import java.time.LocalDate; import java.time.LocalTime; @@ -22,67 +24,68 @@ class ReservationTimeServiceTest { - private ReservationTimeRepository reservationTimeRepository; + private static final int INITIAL_TIME_COUNT = 3; + private ReservationTimeService reservationTimeService; @BeforeEach - void setUp() { // 테케 의존성 분리하기 + void setUp() { ReservationTimeDao reservationTimeDao = new FakeReservationTimeDao(new ArrayList<>(List.of( - new ReservationTime(1, LocalTime.of(10, 0)), - new ReservationTime(2, LocalTime.of(11, 0))))); + new ReservationTime(1, LocalTime.of(1, 0)), + new ReservationTime(2, LocalTime.of(2, 0)), + new ReservationTime(3, LocalTime.of(3, 0))))); ReservationDao reservationDao = new FakeReservationDao(new ArrayList<>(List.of( - new ReservationSavedDto(1, "브라운", LocalDate.of(2030, 8, 5), 2L, 1L), - new ReservationSavedDto(1, "리사", LocalDate.of(2030, 8, 1), 2L, 2L)))); - reservationTimeRepository = new ReservationTimeRepository(reservationDao, reservationTimeDao); - reservationTimeService = new ReservationTimeService(reservationTimeRepository); + new ReservationSavedDto(1, "n1", LocalDate.of(2000, 1, 1), 1L, 1L), + new ReservationSavedDto(2, "n2", LocalDate.of(2000, 1, 2), 2L, 2L)))); + reservationTimeService = new ReservationTimeService(new ReservationTimeRepository(reservationDao, reservationTimeDao)); } - @DisplayName("모든 예약 시간을 반환한다") + @DisplayName("모든 예약 시간을 조회한다.") @Test - void should_return_all_reservation_times() { + void should_find_all_reservation_times() { List reservationTimes = reservationTimeService.findAllReservationTimes(); - assertThat(reservationTimes).hasSize(2); + assertThat(reservationTimes).hasSize(INITIAL_TIME_COUNT); } - @DisplayName("아이디에 해당하는 예약 시간을 반환한다.") + @DisplayName("특정 id에 해당하는 예약 시간을 조회한다.") @Test - void should_get_reservation_time() { - ReservationTime reservationTime = reservationTimeService.findReservationTime(2); - assertThat(reservationTime.getStartAt()).isEqualTo(LocalTime.of(11, 0)); + void should_find_reservation_time_by_id() { + ReservationTime expected = new ReservationTime(1, LocalTime.of(1, 0)); + ReservationTime actual = reservationTimeService.findReservationTime(1); + assertThat(actual).isEqualTo(expected); } @DisplayName("예약 시간을 추가한다") @Test - void should_add_reservation_times() { - reservationTimeService.saveReservationTime(new ReservationTimeDto(LocalTime.of(12, 0))); - List allReservationTimes = reservationTimeService.findAllReservationTimes(); - assertThat(allReservationTimes).hasSize(3); + void should_save_reservation_time() { + ReservationTimeDto timeDto = new ReservationTimeDto(LocalTime.of(4, 0)); + reservationTimeService.saveReservationTime(timeDto); + assertThat(reservationTimeService.findAllReservationTimes()).hasSize(INITIAL_TIME_COUNT + 1); } - @DisplayName("예약 시간을 삭제한다") + @DisplayName("예약 시간을 삭제한다.") @Test - void should_remove_reservation_times() { - reservationTimeService.deleteReservationTime(1); - List allReservationTimes = reservationTimeService.findAllReservationTimes(); - assertThat(allReservationTimes).hasSize(1); + void should_delete_reservation_time() { + reservationTimeService.deleteReservationTime(3); + assertThat(reservationTimeService.findAllReservationTimes()).hasSize(INITIAL_TIME_COUNT - 1); } - @DisplayName("존재하지 않는 시간이면 예외를 발생시킨다.") + @DisplayName("예약 시간을 삭제하려 할 때 특정 id를 가진 예약 시간이 존재하는 경우 예외가 발생하지 않는다.") @Test - void should_throw_exception_when_not_exist_id() { - assertThatThrownBy(() -> reservationTimeService.deleteReservationTime(10000000)) - .isInstanceOf(NotFoundException.class) - .hasMessage("[ERROR] 존재하지 않는 시간입니다."); + void should_not_throw_exception_when_exist_id() { + assertThatCode(() -> reservationTimeService.deleteReservationTime(3)) + .doesNotThrowAnyException(); } - @DisplayName("존재하는 시간이면 예외가 발생하지 않는다.") + @DisplayName("예약 시간을 삭제하려 할 때 특정 id를 가진 예약 시간이 존재하지 않는 경우 예외가 발생한다.") @Test - void should_not_throw_exception_when_exist_id() { - assertThatCode(() -> reservationTimeService.deleteReservationTime(1)) - .doesNotThrowAnyException(); + void should_throw_exception_when_not_exist_id() { + assertThatThrownBy(() -> reservationTimeService.deleteReservationTime(999)) + .isInstanceOf(NotFoundException.class) + .hasMessage("[ERROR] 존재하지 않는 시간입니다."); } - @DisplayName("특정 시간에 대핸 예약이 존재하는데, 그 시간을 삭제하려 할 때 예외가 발생한다.") + @DisplayName("예약 시간을 삭제하려 할 때 해당 시간을 사용하는 예약이 존재하는 경우 예외가 발생한다.") @Test void should_throw_exception_when_exist_reservation_using_time() { assertThatThrownBy(() -> reservationTimeService.deleteReservationTime(2)) @@ -90,10 +93,11 @@ void should_throw_exception_when_exist_reservation_using_time() { .hasMessage("[ERROR] 해당 시간을 사용하고 있는 예약이 있습니다."); } - @DisplayName("존재하는 시간을 추가하려 할 때 예외가 발생한다.") + @DisplayName("이미 존재하는 예약 시간을 중복으로 추가하려 할 때 예외가 발생한다.") @Test void should_throw_exception_when_add_exist_time() { - assertThatThrownBy(() -> reservationTimeService.saveReservationTime(new ReservationTimeDto(LocalTime.of(10, 0)))) + ReservationTimeDto timeDto = new ReservationTimeDto(LocalTime.of(1, 0)); + assertThatThrownBy(() -> reservationTimeService.saveReservationTime(timeDto)) .isInstanceOf(DuplicatedException.class) .hasMessage("[ERROR] 중복되는 시간은 추가할 수 없습니다."); } diff --git a/src/test/java/roomescape/service/ThemeServiceTest.java b/src/test/java/roomescape/service/ThemeServiceTest.java index 17a7059c0e..9274c69899 100644 --- a/src/test/java/roomescape/service/ThemeServiceTest.java +++ b/src/test/java/roomescape/service/ThemeServiceTest.java @@ -9,6 +9,8 @@ import roomescape.repository.dao.ThemeDao; import roomescape.repository.dto.ReservationSavedDto; import roomescape.service.dto.ThemeDto; +import roomescape.service.fakedao.FakeReservationDao; +import roomescape.service.fakedao.FakeThemeDao; import java.time.LocalDate; import java.util.ArrayList; @@ -18,48 +20,47 @@ class ThemeServiceTest { + private static final int INITIAL_THEME_COUNT = 2; + private ThemeService themeService; - private ThemeRepository themeRepository; @BeforeEach - void setUp() { // 테케 의존성 분리하기 + void setUp() { ThemeDao themeDao = new FakeThemeDao(new ArrayList<>(List.of( - new Theme(1, "에버", "공포", "공포.jpg"), - new Theme(2, "배키", "미스터리", "미스터리.jpg"), - new Theme(3, "포비", "스릴러", "스릴러.jpg")))); + new Theme(1, "n1", "d1", "t1"), + new Theme(2, "n2", "d2", "t2")))); ReservationDao reservationDao = new FakeReservationDao(new ArrayList<>(List.of( - new ReservationSavedDto(1, "브라운", LocalDate.of(2030, 8, 5), 2L, 1L), - new ReservationSavedDto(1, "리사", LocalDate.of(2030, 8, 1), 2L, 2L)))); - themeRepository = new ThemeRepository(reservationDao, themeDao); - themeService = new ThemeService(themeRepository); + new ReservationSavedDto(1, "n1", LocalDate.now().minusDays(1), 1L, 1L), + new ReservationSavedDto(2, "n2", LocalDate.now().minusDays(8), 2L, 2L)))); + themeService = new ThemeService(new ThemeRepository(reservationDao, themeDao)); } - @DisplayName("테마를 조회한다.") + @DisplayName("모든 테마를 조회한다.") @Test void should_find_all_themes() { - assertThat(themeService.findAllThemes()).hasSize(3); + List themes = themeService.findAllThemes(); + assertThat(themes).hasSize(INITIAL_THEME_COUNT); } @DisplayName("테마를 저장한다.") @Test - void should_add_theme() { - ThemeDto themeDto = new ThemeDto("에버", "공포", "공포.jpg"); + void should_save_theme() { + ThemeDto themeDto = new ThemeDto("n3", "d3", "t3"); themeService.saveTheme(themeDto); - assertThat(themeService.findAllThemes()).hasSize(4); + assertThat(themeService.findAllThemes()).hasSize(INITIAL_THEME_COUNT + 1); } @DisplayName("테마를 삭제한다.") @Test void should_delete_theme() { - themeService.deleteTheme(1L); - assertThat(themeService.findAllThemes()).hasSize(2); + themeService.deleteTheme(1); + assertThat(themeService.findAllThemes()).hasSize(INITIAL_THEME_COUNT - 1); } @DisplayName("최근 일주일 간 가장 인기 있는 테마 10개를 조회한다.") @Test - void should_find_popular_theme_of_week() { + void should_find_popular_theme_of_week() { // TODO: test case 구체화 List popularThemes = themeService.findPopularThemes(); - // TODO: now 라서 인기 테마 존재하지 않음 - assertThat(popularThemes).hasSize(0); + assertThat(popularThemes).hasSize(2); } } \ No newline at end of file diff --git a/src/test/java/roomescape/service/FakeReservationDao.java b/src/test/java/roomescape/service/fakedao/FakeReservationDao.java similarity index 90% rename from src/test/java/roomescape/service/FakeReservationDao.java rename to src/test/java/roomescape/service/fakedao/FakeReservationDao.java index afc2ebaafb..e4e3ccfb18 100644 --- a/src/test/java/roomescape/service/FakeReservationDao.java +++ b/src/test/java/roomescape/service/fakedao/FakeReservationDao.java @@ -1,4 +1,4 @@ -package roomescape.service; +package roomescape.service.fakedao; import roomescape.model.Reservation; import roomescape.repository.dao.ReservationDao; @@ -9,17 +9,9 @@ import java.util.concurrent.atomic.AtomicLong; import java.util.stream.Collectors; -class FakeReservationDao implements ReservationDao { +public class FakeReservationDao implements ReservationDao { private final AtomicLong index = new AtomicLong(3); // TODO: change to 1 -// private final List reservationTimes = new ArrayList<>(List.of( -// new ReservationTime(1, LocalTime.of(10, 0)), -// new ReservationTime(2, LocalTime.of(11, 0)))); -// -// private final List themes = new ArrayList<>(List.of( -// new Theme(1, "에버", "공포", "공포.jpg"), -// new Theme(1, "배키", "스릴러", "스릴러.jpg"))); - private final List reservations; public FakeReservationDao(List reservations) { @@ -60,7 +52,8 @@ public List findByDateAndThemeId(LocalDate date, long theme public List findThemeIdByDateAndOrderByThemeIdCountAndLimit(LocalDate startDate, LocalDate endDate, int limit) { // Filter reservations by date List filteredReservations = reservations.stream() - .filter(reservation -> reservation.getDate().isAfter(startDate) && reservation.getDate().isBefore(endDate)) + .filter(reservation -> reservation.getDate().isAfter(startDate) || reservation.getDate().isEqual(startDate) + && reservation.getDate().isBefore(endDate) || reservation.getDate().isEqual(endDate)) .toList(); // Count reservations by themeId diff --git a/src/test/java/roomescape/service/FakeReservationTimeDao.java b/src/test/java/roomescape/service/fakedao/FakeReservationTimeDao.java similarity index 94% rename from src/test/java/roomescape/service/FakeReservationTimeDao.java rename to src/test/java/roomescape/service/fakedao/FakeReservationTimeDao.java index 7c1e13d45d..41ff6970f3 100644 --- a/src/test/java/roomescape/service/FakeReservationTimeDao.java +++ b/src/test/java/roomescape/service/fakedao/FakeReservationTimeDao.java @@ -1,4 +1,4 @@ -package roomescape.service; +package roomescape.service.fakedao; import roomescape.model.ReservationTime; import roomescape.repository.dao.ReservationTimeDao; @@ -10,7 +10,7 @@ import java.util.Optional; import java.util.concurrent.atomic.AtomicLong; -class FakeReservationTimeDao implements ReservationTimeDao { +public class FakeReservationTimeDao implements ReservationTimeDao { private final AtomicLong index = new AtomicLong(1); private final List reservationTimes = new ArrayList<>(); diff --git a/src/test/java/roomescape/service/FakeThemeDao.java b/src/test/java/roomescape/service/fakedao/FakeThemeDao.java similarity index 97% rename from src/test/java/roomescape/service/FakeThemeDao.java rename to src/test/java/roomescape/service/fakedao/FakeThemeDao.java index 52be902008..38f066aa78 100644 --- a/src/test/java/roomescape/service/FakeThemeDao.java +++ b/src/test/java/roomescape/service/fakedao/FakeThemeDao.java @@ -1,4 +1,4 @@ -package roomescape.service; +package roomescape.service.fakedao; import roomescape.model.Theme; import roomescape.repository.dao.ThemeDao; From 3370afa79700e6ae93e784b2707efda8785682c8 Mon Sep 17 00:00:00 2001 From: SCY Date: Sun, 5 May 2024 21:24:49 +0900 Subject: [PATCH 55/74] =?UTF-8?q?refactor(FakeReservationDao):=20=EB=B6=88?= =?UTF-8?q?=ED=95=84=EC=9A=94=ED=95=9C=20=EC=A3=BC=EC=84=9D=20=EB=B0=8F=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/fakedao/FakeReservationDao.java | 67 ++++++------------- 1 file changed, 20 insertions(+), 47 deletions(-) diff --git a/src/test/java/roomescape/service/fakedao/FakeReservationDao.java b/src/test/java/roomescape/service/fakedao/FakeReservationDao.java index e4e3ccfb18..fdc99b8bc4 100644 --- a/src/test/java/roomescape/service/fakedao/FakeReservationDao.java +++ b/src/test/java/roomescape/service/fakedao/FakeReservationDao.java @@ -50,60 +50,33 @@ public List findByDateAndThemeId(LocalDate date, long theme @Override public List findThemeIdByDateAndOrderByThemeIdCountAndLimit(LocalDate startDate, LocalDate endDate, int limit) { - // Filter reservations by date - List filteredReservations = reservations.stream() - .filter(reservation -> reservation.getDate().isAfter(startDate) || reservation.getDate().isEqual(startDate) - && reservation.getDate().isBefore(endDate) || reservation.getDate().isEqual(endDate)) + List filteredReservations = findBetweenDates(startDate, endDate); + Map countOfThemeIds = countByThemeId(filteredReservations); + return sortByCountAndLimit(countOfThemeIds); + } + + private List findBetweenDates(LocalDate startDate, LocalDate endDate) { + return reservations.stream() + .filter(reservation -> isBetweenDate(reservation.getDate(), startDate, endDate)) .toList(); + } + + private boolean isBetweenDate(LocalDate target, LocalDate startDate, LocalDate endDate) { + return target.isAfter(startDate) || target.isEqual(startDate) + && target.isBefore(endDate) || target.isEqual(endDate); + } - // Count reservations by themeId - Map countOfThemeIds = filteredReservations.stream() + private Map countByThemeId(List filteredReservations) { + return filteredReservations.stream() .collect(Collectors.groupingBy(ReservationSavedDto::getThemeId, Collectors.counting())); - // Sort themeIds by count - List finalThemeIds = countOfThemeIds.entrySet().stream() + } + + private List sortByCountAndLimit(Map countOfThemeIds) { + return countOfThemeIds.entrySet().stream() .sorted(Map.Entry.comparingByValue().reversed()) .limit(10) .map(Map.Entry::getKey) .toList(); - // Filter reservations by top 10 themeIds - return finalThemeIds; - - /* - // find by date - List filteredReservations = reservations.stream() - .filter(reservation -> reservation.getDate().isBefore(endDate) && reservation.getDate().isAfter(startDate)) - .toList(); - - // group by themeId - List filteredThemeIds = filteredReservations.stream() - .map(ReservationSavedDto::getThemeId) - .collect(Collectors.toList()); - - // order by count - Map countOfThemeIds = new HashMap<>(); - for (Long filteredThemeId : filteredThemeIds) { - long count = filteredThemeIds.stream() - .filter(id -> id.equals(filteredThemeId)) - .count(); - countOfThemeIds.put(filteredThemeId, count); - } - filteredThemeIds.sort(Comparator.comparingLong(countOfThemeIds::get)); - - // limit 10 - List themeIds = filteredThemeIds.stream().distinct().toList(); - List finalThemeIds = themeIds.subList(0, 10); - - // make DTO - List result = new ArrayList<>(); - for (Long finalThemeId : finalThemeIds) { - result.add(filteredReservations.stream() - .filter(reservation -> reservation.getThemeId() == finalThemeId) - .findFirst() - .orElseThrow(NoSuchElementException::new)); - } - return result; - - */ } @Override From 45eeca6c03028e5f1ffecde67f572dc60cd0fe10 Mon Sep 17 00:00:00 2001 From: SCY Date: Sun, 5 May 2024 21:25:15 +0900 Subject: [PATCH 56/74] =?UTF-8?q?fix(js):=20=ED=85=8C=EB=A7=88=20=EC=95=84?= =?UTF-8?q?=EC=9D=B4=EB=94=94=20=EB=A0=8C=EB=8D=94=EB=A7=81=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/static/js/user-reservation.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/static/js/user-reservation.js b/src/main/resources/static/js/user-reservation.js index 2f55b7b3dd..bf6590b089 100644 --- a/src/main/resources/static/js/user-reservation.js +++ b/src/main/resources/static/js/user-reservation.js @@ -37,7 +37,7 @@ function renderTheme(themes) { themeSlots.innerHTML = ''; themes.forEach(theme => { const name = theme.name; - const themeId = theme.themeId; + const themeId = theme.id; /* TODO: 완료 [3단계] 사용자 예약 - 테마 목록 조회 API 호출 후 렌더링 response 명세에 맞춰 createSlot 함수 호출 시 값 설정 From fd50d94ac05a66716b0774ea8d7f2fed7519d292 Mon Sep 17 00:00:00 2001 From: SCY Date: Mon, 6 May 2024 18:47:44 +0900 Subject: [PATCH 57/74] =?UTF-8?q?refactor(controllerTest):=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=BB=A8=EB=B2=A4=EC=85=98=20=ED=86=B5?= =?UTF-8?q?=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/dao/JdbcReservationDao.java | 2 +- .../controller/ReservationControllerTest.java | 160 +++++++++------ .../ReservationTimeControllerTest.java | 73 +++++-- .../controller/ThemeControllerTest.java | 191 ++++++++++-------- 4 files changed, 255 insertions(+), 171 deletions(-) diff --git a/src/main/java/roomescape/repository/dao/JdbcReservationDao.java b/src/main/java/roomescape/repository/dao/JdbcReservationDao.java index 1bba2c2705..93ee7afa77 100644 --- a/src/main/java/roomescape/repository/dao/JdbcReservationDao.java +++ b/src/main/java/roomescape/repository/dao/JdbcReservationDao.java @@ -79,7 +79,7 @@ public List findThemeIdByDateAndOrderByThemeIdCountAndLimit(LocalDate star from reservation where date between ? and ? group by theme_id - order by count(theme_id) desc + order by count(theme_id) desc, theme_id asc limit ? """; return jdbcTemplate.query(sql, (resultSet, rowNum) -> resultSet.getLong("theme_id"), diff --git a/src/test/java/roomescape/controller/ReservationControllerTest.java b/src/test/java/roomescape/controller/ReservationControllerTest.java index 975c53572e..4fd5ddf2dc 100644 --- a/src/test/java/roomescape/controller/ReservationControllerTest.java +++ b/src/test/java/roomescape/controller/ReservationControllerTest.java @@ -2,64 +2,113 @@ import io.restassured.RestAssured; import io.restassured.http.ContentType; -import org.assertj.core.api.AssertionsForClassTypes; +import org.junit.jupiter.api.BeforeEach; 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.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.simple.SimpleJdbcInsert; import org.springframework.test.annotation.DirtiesContext; import roomescape.controller.request.ReservationRequest; import roomescape.controller.response.MemberReservationTimeResponse; import roomescape.controller.response.ReservationResponse; -import java.lang.reflect.Field; import java.time.LocalDate; import java.time.LocalTime; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.stream.IntStream; import static org.assertj.core.api.Assertions.assertThat; - @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) -@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) +@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) class ReservationControllerTest { - @Autowired - private JdbcTemplate jdbcTemplate; + private static final int INITIAL_TIME_COUNT = 5; + private static final int INITIAL_RESERVATION_COUNT = 15; + + private final JdbcTemplate jdbcTemplate; + private final SimpleJdbcInsert themeInsertActor; + private final SimpleJdbcInsert timeInsertActor; + private final SimpleJdbcInsert reservationInsertActor; @Autowired - private ReservationController reservationController; + public ReservationControllerTest(JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + this.themeInsertActor = new SimpleJdbcInsert(jdbcTemplate) + .withTableName("theme") + .usingGeneratedKeyColumns("id"); + this.timeInsertActor = new SimpleJdbcInsert(jdbcTemplate) + .withTableName("reservation_time") + .usingGeneratedKeyColumns("id"); + this.reservationInsertActor = new SimpleJdbcInsert(jdbcTemplate) + .withTableName("reservation") + .usingGeneratedKeyColumns("id"); + } - @DisplayName("예약을 조회한다.") - @Test - void should_get_reservations() { - jdbcTemplate.update("INSERT INTO reservation_time (start_at) VALUES (?)", "10:00"); - jdbcTemplate.update("INSERT INTO theme (name, description, thumbnail) VALUES (?, ?, ?)", "에버", "공포", "공포.jpg"); - jdbcTemplate.update("INSERT INTO reservation (name, date, time_id, theme_id) VALUES (?, ?, ?, ?)", "브라운", "2030-08-05", "1", "1"); + @BeforeEach + void setUp() { + initDatabase(); + IntStream.range(1, 6).forEach(i -> insertReservationTime(i + ":00")); + IntStream.range(0, 20).forEach(i -> insertTheme("n" + i, "d" + i, "t" + i)); + + LocalDate date = LocalDate.now().minusDays(1); + IntStream.range(0, 1).forEach(i -> insertReservation("n" + i, date, 1, 1)); + IntStream.range(0, 2).forEach(i -> insertReservation("n" + i, date, 1, 2)); + IntStream.range(0, 3).forEach(i -> insertReservation("n" + i, date, 1, 3)); + IntStream.range(0, 4).forEach(i -> insertReservation("n" + i, date, 2, 1)); + IntStream.range(0, 5).forEach(i -> insertReservation("n" + i, date, 2, 2)); + } + + private void initDatabase() { + jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY FALSE"); + jdbcTemplate.execute("TRUNCATE TABLE theme RESTART IDENTITY"); + jdbcTemplate.execute("TRUNCATE TABLE reservation_time RESTART IDENTITY"); + jdbcTemplate.execute("TRUNCATE TABLE reservation RESTART IDENTITY"); + } + + private void insertTheme(String name, String description, String thumbnail) { + Map parameters = new HashMap<>(3); + parameters.put("name", name); + parameters.put("description", description); + parameters.put("thumbnail", thumbnail); + themeInsertActor.execute(parameters); + } + + private void insertReservationTime(String startAt) { + Map parameters = new HashMap<>(1); + parameters.put("start_at", startAt); + timeInsertActor.execute(parameters); + } + + private void insertReservation(String name, LocalDate date, long timeId, long themeId) { + Map parameters = new HashMap<>(4); + parameters.put("name", name); + parameters.put("date", date); + parameters.put("time_id", timeId); + parameters.put("theme_id", themeId); + reservationInsertActor.execute(parameters); + } + @DisplayName("전체 예약을 조회한다.") + @Test + void should_get_all_reservations() { List reservations = RestAssured.given().log().all() .when().get("/reservations") .then().log().all() - .statusCode(200).extract() - .jsonPath().getList(".", ReservationResponse.class); - - Integer count = jdbcTemplate.queryForObject("SELECT count(1) from reservation", Integer.class); + .statusCode(200) + .extract().jsonPath().getList(".", ReservationResponse.class); - assertThat(reservations).hasSize(count); + assertThat(reservations).hasSize(INITIAL_RESERVATION_COUNT); } @DisplayName("예약을 추가할 수 있다.") @Test void should_insert_reservation() { - jdbcTemplate.update("INSERT INTO reservation_time (start_at) VALUES (?)", "10:00"); - jdbcTemplate.update("INSERT INTO theme (name, description, thumbnail) VALUES (?, ?, ?)", "에버", "공포", "공포.jpg"); - - ReservationRequest request = new ReservationRequest( - "브라운", - LocalDate.of(2030, 8, 5), - 1L, - 1L); + ReservationRequest request = new ReservationRequest("n", LocalDate.now().plusDays(1), 1L, 1L); RestAssured.given().log().all() .contentType(ContentType.JSON) @@ -67,61 +116,44 @@ void should_insert_reservation() { .when().post("/reservations") .then().log().all() .statusCode(201) - .header("Location", "/reservations/1"); + .header("Location", "/reservations/" + (INITIAL_RESERVATION_COUNT + 1)); - Integer count = jdbcTemplate.queryForObject("SELECT count(1) from reservation", Integer.class); - AssertionsForClassTypes.assertThat(count).isEqualTo(1); + assertThat(countAllReservations()).isEqualTo(INITIAL_RESERVATION_COUNT + 1); } @DisplayName("존재하는 예약이라면 예약을 삭제할 수 있다.") @Test void should_delete_reservation_when_reservation_exist() { - jdbcTemplate.update( - "INSERT INTO reservation_time (start_at) VALUES (?)", - "10:00"); - jdbcTemplate.update( - "INSERT INTO reservation (name, date, time_id) VALUES (?, ?, ?)", - "브라운", "2023-08-05", "1"); - RestAssured.given().log().all() .when().delete("/reservations/1") .then().log().all() .statusCode(204); - Integer countAfterDelete = jdbcTemplate.queryForObject("SELECT count(1) from reservation", Integer.class); - AssertionsForClassTypes.assertThat(countAfterDelete).isZero(); - } - - @DisplayName("컨트롤러에 JdbcTemplate 필드가 존재하지 않는다.") - @Test - void should_not_exist_JdbcTemplate_field() { - boolean isJdbcTemplateInjected = false; - - for (Field field : reservationController.getClass().getDeclaredFields()) { - if (field.getType().equals(JdbcTemplate.class)) { - isJdbcTemplateInjected = true; - break; - } - } - - AssertionsForClassTypes.assertThat(isJdbcTemplateInjected).isFalse(); + assertThat(countAllReservations()).isEqualTo(INITIAL_RESERVATION_COUNT - 1); } @DisplayName("특정 날짜와 테마에 따른 모든 시간의 예약 가능 여부를 확인한다.") @Test void should_get_reservations_with_book_state_by_date_and_theme() { - jdbcTemplate.update("INSERT INTO reservation (name, date, time_id, theme_id) VALUES (?, ?, ?, ?)", "브라운", "2030-08-05", "1", "1"); - - List responses = RestAssured.given().log().all() - .when().get("/reservations/times?date=2030-08-05&themeId=1") + String date = LocalDate.now().minusDays(1).toString(); // LD 으로 바꾸어보자! + long themeId = 1; + List times = RestAssured.given().log().all() + .when().get(String.format("/reservations/times?date=%s&themeId=%d", date, themeId)) .then().log().all() - .statusCode(200).extract() - .jsonPath().getList(".", MemberReservationTimeResponse.class); - - assertThat(responses).hasSize(2); - assertThat(responses).containsOnly( - new MemberReservationTimeResponse(1, LocalTime.of(10, 0), true), - new MemberReservationTimeResponse(2, LocalTime.of(11, 0), false) + .statusCode(200) + .extract().jsonPath().getList(".", MemberReservationTimeResponse.class); + System.out.println(times); + assertThat(times).hasSize(INITIAL_TIME_COUNT); + assertThat(times).containsOnly( + new MemberReservationTimeResponse(1, LocalTime.of(1, 0), true), + new MemberReservationTimeResponse(2, LocalTime.of(2, 0), true), + new MemberReservationTimeResponse(3, LocalTime.of(3, 0), false), + new MemberReservationTimeResponse(4, LocalTime.of(4, 0), false), + new MemberReservationTimeResponse(5, LocalTime.of(5, 0), false) ); } + + private Integer countAllReservations() { + return jdbcTemplate.queryForObject("SELECT count(id) from reservation", Integer.class); + } } diff --git a/src/test/java/roomescape/controller/ReservationTimeControllerTest.java b/src/test/java/roomescape/controller/ReservationTimeControllerTest.java index b03d360db4..1bd9d0672e 100644 --- a/src/test/java/roomescape/controller/ReservationTimeControllerTest.java +++ b/src/test/java/roomescape/controller/ReservationTimeControllerTest.java @@ -2,48 +2,75 @@ import io.restassured.RestAssured; import io.restassured.http.ContentType; -import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeEach; 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.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.simple.SimpleJdbcInsert; import org.springframework.test.annotation.DirtiesContext; import roomescape.controller.request.ReservationTimeRequest; import roomescape.model.ReservationTime; import java.time.LocalTime; +import java.util.HashMap; import java.util.List; +import java.util.Map; -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) -@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) +@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) class ReservationTimeControllerTest { + private static final int INITIAL_TIME_COUNT = 2; + + private final JdbcTemplate jdbcTemplate; + private final SimpleJdbcInsert timeInsertActor; + @Autowired - JdbcTemplate jdbcTemplate; + public ReservationTimeControllerTest(JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + this.timeInsertActor = new SimpleJdbcInsert(jdbcTemplate) + .withTableName("reservation_time") + .usingGeneratedKeyColumns("id"); + } - @DisplayName("모든 예약 시간을 조회한다") - @Test - void should_get_reservation_times() { - jdbcTemplate.update("INSERT INTO reservation_time (start_at) values (?)", "10:00"); + @BeforeEach + void setUp() { + initDatabase(); + insertReservationTime("1:00"); + insertReservationTime("2:00"); + } + + private void initDatabase() { + jdbcTemplate.execute("ALTER TABLE reservation_time SET REFERENTIAL_INTEGRITY FALSE"); + jdbcTemplate.execute("TRUNCATE TABLE reservation_time RESTART IDENTITY"); + } + private void insertReservationTime(String startAt) { + Map parameters = new HashMap<>(1); + parameters.put("start_at", startAt); + timeInsertActor.execute(parameters); + } + + @DisplayName("모든 예약 시간을 조회한다.") + @Test + void should_get_all_reservation_times() { List reservationTimes = RestAssured.given().log().all() .when().get("/times") .then().log().all() - .statusCode(200).extract() - .jsonPath().getList(".", ReservationTime.class); + .statusCode(200) + .extract().jsonPath().getList(".", ReservationTime.class); - Integer count = jdbcTemplate.queryForObject("SELECT count(1) from reservation_time", Integer.class); - - Assertions.assertThat(reservationTimes).hasSize(count); + assertThat(reservationTimes).hasSize(INITIAL_TIME_COUNT); } - @DisplayName("예약 시간을 추가한다") + @DisplayName("예약 시간을 추가한다.") @Test - void should_add_reservation_times() { - ReservationTimeRequest request = new ReservationTimeRequest(LocalTime.of(12, 0)); + void should_add_reservation_time() { + ReservationTimeRequest request = new ReservationTimeRequest(LocalTime.of(3, 0)); RestAssured.given().log().all() .contentType(ContentType.JSON) @@ -51,13 +78,12 @@ void should_add_reservation_times() { .when().post("/times") .then().log().all() .statusCode(201) - .header("Location", "/times/3"); + .header("Location", "/times/" + (INITIAL_TIME_COUNT + 1)); - Integer count = jdbcTemplate.queryForObject("SELECT count(1) from reservation_time", Integer.class); - assertThat(count).isEqualTo(3); + assertThat(countAllTimes()).isEqualTo(INITIAL_TIME_COUNT + 1); } - @DisplayName("예약 시간을 삭제한다") + @DisplayName("예약 시간을 삭제한다.") @Test void should_remove_reservation_time() { RestAssured.given().log().all() @@ -65,7 +91,10 @@ void should_remove_reservation_time() { .then().log().all() .statusCode(204); - Integer count = jdbcTemplate.queryForObject("SELECT count(1) from reservation_time", Integer.class); - assertThat(count).isEqualTo(1); + assertThat(countAllTimes()).isEqualTo(INITIAL_TIME_COUNT - 1); + } + + private Integer countAllTimes() { + return jdbcTemplate.queryForObject("SELECT count(id) from reservation_time", Integer.class); } } diff --git a/src/test/java/roomescape/controller/ThemeControllerTest.java b/src/test/java/roomescape/controller/ThemeControllerTest.java index f9a72b942f..53312b57ca 100644 --- a/src/test/java/roomescape/controller/ThemeControllerTest.java +++ b/src/test/java/roomescape/controller/ThemeControllerTest.java @@ -14,151 +14,174 @@ import roomescape.controller.response.ThemeResponse; import java.time.LocalDate; -import java.time.LocalTime; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.stream.IntStream; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertAll; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) -@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) +@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) class ThemeControllerTest { - @Autowired - private JdbcTemplate jdbcTemplate; + private static final int INITIAL_THEME_COUNT = 20; - private SimpleJdbcInsert reservationInsertActor; - private SimpleJdbcInsert timeInsertActor; - private SimpleJdbcInsert themeInsertActor; + private final JdbcTemplate jdbcTemplate; + private final SimpleJdbcInsert themeInsertActor; + private final SimpleJdbcInsert timeInsertActor; + private final SimpleJdbcInsert reservationInsertActor; - @BeforeEach - void setUp() { - reservationInsertActor = new SimpleJdbcInsert(jdbcTemplate) - .withTableName("reservation") + @Autowired + public ThemeControllerTest(JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + this.themeInsertActor = new SimpleJdbcInsert(jdbcTemplate) + .withTableName("theme") .usingGeneratedKeyColumns("id"); - timeInsertActor = new SimpleJdbcInsert(jdbcTemplate) + this.timeInsertActor = new SimpleJdbcInsert(jdbcTemplate) .withTableName("reservation_time") .usingGeneratedKeyColumns("id"); - themeInsertActor = new SimpleJdbcInsert(jdbcTemplate) - .withTableName("theme") + this.reservationInsertActor = new SimpleJdbcInsert(jdbcTemplate) + .withTableName("reservation") .usingGeneratedKeyColumns("id"); } + @BeforeEach + void setUp() { + initDatabase(); + IntStream.range(1, 3).forEach(i -> insertReservationTime(i + ":00")); + IntStream.range(0, 20).forEach(i -> insertTheme("n" + i, "d" + i, "t" + i)); + + LocalDate date = LocalDate.now().minusDays(1); + IntStream.range(0, 1).forEach(i -> insertReservation("n" + i, date, 1, 1)); + IntStream.range(0, 2).forEach(i -> insertReservation("n" + i, date, 1, 2)); + IntStream.range(0, 3).forEach(i -> insertReservation("n" + i, date, 1, 3)); + IntStream.range(0, 4).forEach(i -> insertReservation("n" + i, date, 2, 4)); + IntStream.range(0, 5).forEach(i -> insertReservation("n" + i, date, 2, 5)); + } + + private void initDatabase() { + jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY FALSE"); + jdbcTemplate.execute("TRUNCATE TABLE theme RESTART IDENTITY"); + jdbcTemplate.execute("TRUNCATE TABLE reservation_time RESTART IDENTITY"); + jdbcTemplate.execute("TRUNCATE TABLE reservation RESTART IDENTITY"); + } + + private void insertTheme(String name, String description, String thumbnail) { + Map parameters = new HashMap<>(3); + parameters.put("name", name); + parameters.put("description", description); + parameters.put("thumbnail", thumbnail); + themeInsertActor.execute(parameters); + } + + private void insertReservationTime(String startAt) { + Map parameters = new HashMap<>(1); + parameters.put("start_at", startAt); + timeInsertActor.execute(parameters); + } + + private void insertReservation(String name, LocalDate date, long timeId, long themeId) { + Map parameters = new HashMap<>(4); + parameters.put("name", name); + parameters.put("date", date); + parameters.put("time_id", timeId); + parameters.put("theme_id", themeId); + reservationInsertActor.execute(parameters); + } + @DisplayName("전체 테마를 조회한다.") @Test - void should_get_themes() { - jdbcTemplate.update("INSERT INTO theme (name, description, thumbnail) VALUES (?, ?, ?)", "에버", "공포", "공포.jpg"); - jdbcTemplate.update("INSERT INTO theme (name, description, thumbnail) VALUES (?, ?, ?)", "배키", "미스터리", "미스터리.jpg"); - jdbcTemplate.update("INSERT INTO theme (name, description, thumbnail) VALUES (?, ?, ?)", "포비", "스릴러", "스릴러.jpg"); - + void should_get_all_themes() { List themes = RestAssured.given().log().all() .when().get("/themes") .then().log().all() - .statusCode(200).extract() - .jsonPath().getList(".", ThemeResponse.class); + .statusCode(200) + .extract().jsonPath().getList(".", ThemeResponse.class); - Integer count = jdbcTemplate.queryForObject("SELECT count(1) from theme", Integer.class); - assertThat(themes).hasSize(count); + assertThat(themes).hasSize(INITIAL_THEME_COUNT); } @DisplayName("테마를 추가한다.") @Test void should_add_theme() { - ThemeRequest request = new ThemeRequest("에버", "공포", "공포.jpg"); - + ThemeRequest request = new ThemeRequest("n", "d", "t"); RestAssured.given().log().all() .contentType(ContentType.JSON) .body(request) .when().post("/themes") .then().log().all() .statusCode(201) - .header("Location", "/themes/3"); + .header("Location", "/themes/" + (INITIAL_THEME_COUNT + 1)); - Integer count = jdbcTemplate.queryForObject("SELECT count(1) from theme", Integer.class); - - assertThat(count).isEqualTo(3); + assertThat(countAllThemes()).isEqualTo(INITIAL_THEME_COUNT + 1); } @DisplayName("테마를 삭제한다") @Test void should_remove_theme() { - jdbcTemplate.update("INSERT INTO theme (name, description, thumbnail) VALUES (?, ?, ?)", "에버", "공포", "공포.jpg"); - jdbcTemplate.update("INSERT INTO theme (name, description, thumbnail) VALUES (?, ?, ?)", "배키", "미스터리", "미스터리.jpg"); - RestAssured.given().log().all() .when().delete("/themes/1") .then().log().all() .statusCode(204); - Integer count = jdbcTemplate.queryForObject("SELECT count(1) from theme", Integer.class); - assertThat(count).isEqualTo(3); + assertThat(countAllThemes()).isEqualTo(INITIAL_THEME_COUNT - 1); } - @DisplayName("인기 테마를 조회한다.") + @DisplayName("예약된 전체 테마 개수가 10 이하인 경우 해당 개수만큼의 인기 테마를 인기 순으로 조회한다.") @Test - void should_find_popular_theme() { - jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY FALSE"); - jdbcTemplate.execute("TRUNCATE TABLE theme RESTART IDENTITY"); - jdbcTemplate.execute("SET REFERENTIAL_INTEGRITY TRUE"); - insertReservationTime(LocalTime.of(10, 0)); - for (int i = 1; i <= 15; i++) { - insertTheme("name" + i, "description" + i, "thumbnail" + i); - } - for (int i = 1; i <= 10; i++) { - insertReservation("name" + i, LocalDate.now().minusDays(i % 7 + 1), 1L, i); - } - insertReservation("name11", LocalDate.now().minusDays(1), 1L, 10); - insertReservation("name12", LocalDate.now().minusDays(1), 1L, 10); - insertReservation("name13", LocalDate.now().minusDays(1), 1L, 10); - insertReservation("name14", LocalDate.now().minusDays(1), 1L, 9); - insertReservation("name15", LocalDate.now().minusDays(1), 1L, 9); - - jdbcTemplate.queryForObject("select count(1) from reservation", Long.class); - + void should_find_popular_themes_when_less_than_10() { List popularThemes = RestAssured.given().log().all() .when().get("/themes/rank") .then().log().all() .statusCode(200) - .extract() - .jsonPath().getList(".", ThemeResponse.class); + .extract().jsonPath().getList(".", ThemeResponse.class); - assertThat(popularThemes).hasSize(10); assertAll(() -> { - assertThat(popularThemes.get(0).getId()).isEqualTo(10); - assertThat(popularThemes.get(1).getId()).isEqualTo(9); - assertThat(popularThemes.get(2).getId()).isEqualTo(1); + assertThat(popularThemes).hasSize(5); + assertThat(popularThemes.get(0).getId()).isEqualTo(5); + assertThat(popularThemes.get(1).getId()).isEqualTo(4); + assertThat(popularThemes.get(2).getId()).isEqualTo(3); assertThat(popularThemes.get(3).getId()).isEqualTo(2); - assertThat(popularThemes.get(4).getId()).isEqualTo(3); - assertThat(popularThemes.get(5).getId()).isEqualTo(4); - assertThat(popularThemes.get(6).getId()).isEqualTo(5); - assertThat(popularThemes.get(7).getId()).isEqualTo(6); - assertThat(popularThemes.get(8).getId()).isEqualTo(7); - assertThat(popularThemes.get(9).getId()).isEqualTo(8); + assertThat(popularThemes.get(4).getId()).isEqualTo(1); }); } - private void insertReservationTime(LocalTime startAt) { - Map parameters = new HashMap<>(1); - parameters.put("start_at", startAt); - timeInsertActor.execute(parameters); - } + @DisplayName("예약된 전체 테마 개수가 10 이상인 경우 인기 테마를 인기 순으로 10개 조회한다. 예약 횟수가 같은 경우 theme_id 순으로 조회한다.") + @Test + void should_find_popular_themes_when_more_than_10() { + LocalDate date = LocalDate.now().minusDays(1); + insertReservation("n", date, 1, 6); + insertReservation("n", date, 1, 7); + insertReservation("n", date, 1, 8); + insertReservation("n", date, 1, 9); + insertReservation("n", date, 1, 10); + insertReservation("n", date, 1, 11); + insertReservation("n", date, 1, 12); - private void insertReservation(String name, LocalDate date, long timeId, long themeId) { - Map parameters = new HashMap<>(4); - parameters.put("name", name); - parameters.put("date", date); - parameters.put("time_id", timeId); - parameters.put("theme_id", themeId); - reservationInsertActor.execute(parameters); + List popularThemes = RestAssured.given().log().all() + .when().get("/themes/rank") + .then().log().all() + .statusCode(200) + .extract().jsonPath().getList(".", ThemeResponse.class); + + assertAll(() -> { + assertThat(popularThemes).hasSize(10); + assertThat(popularThemes.get(0).getId()).isEqualTo(5); + assertThat(popularThemes.get(1).getId()).isEqualTo(4); + assertThat(popularThemes.get(2).getId()).isEqualTo(3); + assertThat(popularThemes.get(3).getId()).isEqualTo(2); + assertThat(popularThemes.get(4).getId()).isEqualTo(1); + assertThat(popularThemes.get(5).getId()).isEqualTo(6); + assertThat(popularThemes.get(6).getId()).isEqualTo(7); + assertThat(popularThemes.get(7).getId()).isEqualTo(8); + assertThat(popularThemes.get(8).getId()).isEqualTo(9); + assertThat(popularThemes.get(9).getId()).isEqualTo(10); + }); } - private void insertTheme(String name, String description, String thumbnail) { - Map parameters = new HashMap<>(3); - parameters.put("name", name); - parameters.put("description", description); - parameters.put("thumbnail", thumbnail); - themeInsertActor.execute(parameters); + private Integer countAllThemes() { + return jdbcTemplate.queryForObject("SELECT count(id) from theme", Integer.class); } } From 0f1db66f1393130a6b403db9584983f245a568ee Mon Sep 17 00:00:00 2001 From: SCY Date: Mon, 6 May 2024 20:10:25 +0900 Subject: [PATCH 58/74] =?UTF-8?q?refactor(GlobalExceptionHandler):=20?= =?UTF-8?q?=EB=8F=99=EC=9D=BC=ED=95=9C=20=EB=A1=9C=EC=A7=81=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EC=B2=98=EB=A6=AC=EB=90=98=EB=8A=94=20=EC=97=90?= =?UTF-8?q?=EB=9F=AC=20=ED=95=B8=EB=93=A4=EB=9F=AC=20=ED=86=B5=ED=95=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../roomescape/exception/GlobalExceptionHandler.java | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/main/java/roomescape/exception/GlobalExceptionHandler.java b/src/main/java/roomescape/exception/GlobalExceptionHandler.java index 5d431234e4..488e143ac5 100644 --- a/src/main/java/roomescape/exception/GlobalExceptionHandler.java +++ b/src/main/java/roomescape/exception/GlobalExceptionHandler.java @@ -15,13 +15,8 @@ public ResponseEntity handleNotFoundException(NotFoundException exceptio return new ResponseEntity<>(exception.getMessage(), HttpStatus.NOT_FOUND); } - @ExceptionHandler(value = BadRequestException.class) - public ResponseEntity handleBadRequestException(BadRequestException exception) { - return new ResponseEntity<>(exception.getMessage(), HttpStatus.BAD_REQUEST); - } - - @ExceptionHandler(value = DuplicatedException.class) - public ResponseEntity handleDuplicatedException(DuplicatedException exception) { + @ExceptionHandler(value = {BadRequestException.class, DuplicatedException.class}) + public ResponseEntity handleBadRequestException(RuntimeException exception) { return new ResponseEntity<>(exception.getMessage(), HttpStatus.BAD_REQUEST); } From ef4bcc71f0110fae5d8d5b3dec1da75b61fff8a4 Mon Sep 17 00:00:00 2001 From: SCY Date: Mon, 6 May 2024 21:25:40 +0900 Subject: [PATCH 59/74] =?UTF-8?q?refactor(ReservationDao):=20=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=84=B0=20=EC=A0=80=EC=9E=A5=20=EC=8B=9C=20DTO?= =?UTF-8?q?=EB=A5=BC=20=EC=A0=84=EB=8B=AC=EB=B0=9B=EB=8F=84=EB=A1=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/ReservationRepository.java | 7 +++++- .../repository/dao/JdbcReservationDao.java | 10 ++++----- .../repository/dao/ReservationDao.java | 2 +- .../repository/dto/ReservationSavedDto.java | 19 ++++++++++++++++ .../repository/dao/ReservationDaoTest.java | 6 ++--- .../service/fakedao/FakeReservationDao.java | 22 +++++++++---------- 6 files changed, 44 insertions(+), 22 deletions(-) diff --git a/src/main/java/roomescape/repository/ReservationRepository.java b/src/main/java/roomescape/repository/ReservationRepository.java index 219328d762..b9899239aa 100644 --- a/src/main/java/roomescape/repository/ReservationRepository.java +++ b/src/main/java/roomescape/repository/ReservationRepository.java @@ -50,8 +50,13 @@ public boolean isExistReservationByDateAndTimeId(LocalDate date, long timeId) { } public Reservation saveReservation(Reservation reservation) { - long id = reservationDao.save(reservation); + ReservationSavedDto reservationSavedDto = new ReservationSavedDto( + reservation.getId(), reservation.getName(), reservation.getDate(), + reservation.getTime().getId(), reservation.getTheme().getId()); + long id = reservationDao.save(reservationSavedDto); + System.out.println(id); ReservationSavedDto saved = reservationDao.findById(id).orElseThrow(NoSuchElementException::new); + System.out.println("@@" + saved.getId()); ReservationTime time = reservationTimeDao.findById(saved.getTimeId()).orElseThrow(NoSuchElementException::new); Theme theme = themeDao.findById(saved.getThemeId()).orElseThrow(NoSuchElementException::new); return new Reservation(id, saved.getName(), saved.getDate(), time, theme); diff --git a/src/main/java/roomescape/repository/dao/JdbcReservationDao.java b/src/main/java/roomescape/repository/dao/JdbcReservationDao.java index 93ee7afa77..a4a6d75726 100644 --- a/src/main/java/roomescape/repository/dao/JdbcReservationDao.java +++ b/src/main/java/roomescape/repository/dao/JdbcReservationDao.java @@ -26,12 +26,12 @@ public JdbcReservationDao(JdbcTemplate jdbcTemplate) { } @Override - public long save(Reservation reservation) { + public long save(ReservationSavedDto reservationSavedDto) { Map parameters = new HashMap<>(4); - parameters.put("name", reservation.getName()); - parameters.put("date", reservation.getDate()); - parameters.put("time_id", reservation.getTime().getId()); - parameters.put("theme_id", reservation.getTheme().getId()); + parameters.put("name", reservationSavedDto.getName()); + parameters.put("date", reservationSavedDto.getDate()); + parameters.put("time_id", reservationSavedDto.getTimeId()); + parameters.put("theme_id", reservationSavedDto.getThemeId()); return insertActor.executeAndReturnKey(parameters).longValue(); } diff --git a/src/main/java/roomescape/repository/dao/ReservationDao.java b/src/main/java/roomescape/repository/dao/ReservationDao.java index b128275cbb..6088ebc59a 100644 --- a/src/main/java/roomescape/repository/dao/ReservationDao.java +++ b/src/main/java/roomescape/repository/dao/ReservationDao.java @@ -9,7 +9,7 @@ public interface ReservationDao { - long save(Reservation reservation); + long save(ReservationSavedDto reservationSavedDto); List findAll(); diff --git a/src/main/java/roomescape/repository/dto/ReservationSavedDto.java b/src/main/java/roomescape/repository/dto/ReservationSavedDto.java index 499e536b15..89249fe337 100644 --- a/src/main/java/roomescape/repository/dto/ReservationSavedDto.java +++ b/src/main/java/roomescape/repository/dto/ReservationSavedDto.java @@ -19,6 +19,14 @@ public ReservationSavedDto(long id, String name, LocalDate date, long timeId, lo this.themeId = themeId; } + public ReservationSavedDto(String name, LocalDate date, long timeId, long themeId) { + this.id = 0; + this.name = name; + this.date = date; + this.timeId = timeId; + this.themeId = themeId; + } + public long getId() { return id; } @@ -51,4 +59,15 @@ public boolean equals(Object o) { public int hashCode() { return Objects.hash(id, name, date, timeId, themeId); } + + @Override + public String toString() { + return "ReservationSavedDto{" + + "id=" + id + + ", name='" + name + '\'' + + ", date=" + date + + ", timeId=" + timeId + + ", themeId=" + themeId + + '}'; + } } diff --git a/src/test/java/roomescape/repository/dao/ReservationDaoTest.java b/src/test/java/roomescape/repository/dao/ReservationDaoTest.java index 75d1d55d56..f50be4b605 100644 --- a/src/test/java/roomescape/repository/dao/ReservationDaoTest.java +++ b/src/test/java/roomescape/repository/dao/ReservationDaoTest.java @@ -93,11 +93,9 @@ private void insertTheme(String name, String description, String thumbnail) { @DisplayName("예약을 저장한다.") @Test void should_save_reservation() { - Theme theme = new Theme(1, "n1", "d1", "t1"); - ReservationTime time = new ReservationTime(1, LocalTime.of(1, 0)); - Reservation reservation = new Reservation("n3", LocalDate.of(2000, 1, 3), time, theme); + ReservationSavedDto reservationSavedDto = new ReservationSavedDto("n3", LocalDate.of(2000, 1, 3), 1, 1); - reservationDao.save(reservation); + reservationDao.save(reservationSavedDto); assertThat(reservationDao.findAll()).hasSize(INITIAL_RESERVATION_COUNT + 1); } diff --git a/src/test/java/roomescape/service/fakedao/FakeReservationDao.java b/src/test/java/roomescape/service/fakedao/FakeReservationDao.java index fdc99b8bc4..5ab4a2e97e 100644 --- a/src/test/java/roomescape/service/fakedao/FakeReservationDao.java +++ b/src/test/java/roomescape/service/fakedao/FakeReservationDao.java @@ -1,6 +1,5 @@ package roomescape.service.fakedao; -import roomescape.model.Reservation; import roomescape.repository.dao.ReservationDao; import roomescape.repository.dto.ReservationSavedDto; @@ -11,14 +10,11 @@ public class FakeReservationDao implements ReservationDao { - private final AtomicLong index = new AtomicLong(3); // TODO: change to 1 - private final List reservations; + private final AtomicLong index = new AtomicLong(1); + private final List reservations = new ArrayList<>(); public FakeReservationDao(List reservations) { -// for (ReservationSavedDto dto : reservations) { -// Reservation reservation = new Reservation(dto.getName(), dto.getDate(), dto.); -// } TODO - this.reservations = reservations; + reservations.forEach(this::save); } @Override @@ -27,15 +23,19 @@ public List findAll() { } @Override - public long save(Reservation reservation) { + public long save(ReservationSavedDto rawDto) { long key = index.getAndIncrement(); - ReservationSavedDto saved = new ReservationSavedDto(key, reservation.getName(), reservation.getDate(), reservation.getTime().getId(), reservation.getTheme().getId()); - reservations.add(saved); + ReservationSavedDto reservationSavedDto = new ReservationSavedDto( + key, rawDto.getName(), rawDto.getDate(), + rawDto.getTimeId(), rawDto.getThemeId()); + reservations.add(reservationSavedDto); return key; } @Override public Optional findById(long id) { + System.out.print("findById = " + id); + System.out.println(reservations); return reservations.stream() .filter(reservation -> reservation.getId() == id) .findFirst(); @@ -48,7 +48,7 @@ public List findByDateAndThemeId(LocalDate date, long theme .toList(); } - @Override + @Override // TODO: fake object test! public List findThemeIdByDateAndOrderByThemeIdCountAndLimit(LocalDate startDate, LocalDate endDate, int limit) { List filteredReservations = findBetweenDates(startDate, endDate); Map countOfThemeIds = countByThemeId(filteredReservations); From 62113811f6ef9391eb932c4eec0f56418877ac0c Mon Sep 17 00:00:00 2001 From: SCY Date: Mon, 6 May 2024 22:05:29 +0900 Subject: [PATCH 60/74] =?UTF-8?q?test(fakedao):=20DAO=EC=9D=98=20fake=20?= =?UTF-8?q?=EA=B0=9D=EC=B2=B4=EC=97=90=20=EB=8C=80=ED=95=9C=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/dao/ReservationDaoTest.java | 4 - .../service/fakedao/FakeReservationDao.java | 10 +- .../fakedao/FakeReservationDaoTest.java | 147 ++++++++++++++++++ .../fakedao/FakeReservationTimeDao.java | 2 +- .../fakedao/FakeReservationTimeDaoTest.java | 112 +++++++++++++ .../service/fakedao/FakeThemeDaoTest.java | 83 ++++++++++ 6 files changed, 348 insertions(+), 10 deletions(-) create mode 100644 src/test/java/roomescape/service/fakedao/FakeReservationDaoTest.java create mode 100644 src/test/java/roomescape/service/fakedao/FakeReservationTimeDaoTest.java create mode 100644 src/test/java/roomescape/service/fakedao/FakeThemeDaoTest.java diff --git a/src/test/java/roomescape/repository/dao/ReservationDaoTest.java b/src/test/java/roomescape/repository/dao/ReservationDaoTest.java index f50be4b605..71395a3d0f 100644 --- a/src/test/java/roomescape/repository/dao/ReservationDaoTest.java +++ b/src/test/java/roomescape/repository/dao/ReservationDaoTest.java @@ -8,13 +8,9 @@ import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.simple.SimpleJdbcInsert; import org.springframework.test.annotation.DirtiesContext; -import roomescape.model.Reservation; -import roomescape.model.ReservationTime; -import roomescape.model.Theme; import roomescape.repository.dto.ReservationSavedDto; import java.time.LocalDate; -import java.time.LocalTime; import java.util.HashMap; import java.util.List; import java.util.Map; diff --git a/src/test/java/roomescape/service/fakedao/FakeReservationDao.java b/src/test/java/roomescape/service/fakedao/FakeReservationDao.java index 5ab4a2e97e..56ade073f2 100644 --- a/src/test/java/roomescape/service/fakedao/FakeReservationDao.java +++ b/src/test/java/roomescape/service/fakedao/FakeReservationDao.java @@ -48,11 +48,11 @@ public List findByDateAndThemeId(LocalDate date, long theme .toList(); } - @Override // TODO: fake object test! + @Override public List findThemeIdByDateAndOrderByThemeIdCountAndLimit(LocalDate startDate, LocalDate endDate, int limit) { List filteredReservations = findBetweenDates(startDate, endDate); Map countOfThemeIds = countByThemeId(filteredReservations); - return sortByCountAndLimit(countOfThemeIds); + return sortByCountAndLimit(countOfThemeIds, limit); } private List findBetweenDates(LocalDate startDate, LocalDate endDate) { @@ -71,10 +71,10 @@ private Map countByThemeId(List filteredReserva .collect(Collectors.groupingBy(ReservationSavedDto::getThemeId, Collectors.counting())); } - private List sortByCountAndLimit(Map countOfThemeIds) { + private List sortByCountAndLimit(Map countOfThemeIds, int limit) { return countOfThemeIds.entrySet().stream() .sorted(Map.Entry.comparingByValue().reversed()) - .limit(10) + .limit(limit) .map(Map.Entry::getKey) .toList(); } @@ -84,7 +84,7 @@ public void deleteById(long id) { ReservationSavedDto foundReservation = reservations.stream() .filter(reservation -> reservation.getId() == id) .findFirst() - .orElseThrow(() -> new NoSuchElementException("아이디가 존재하지 않습니다.")); + .orElseThrow(() -> new NoSuchElementException("존재하지 않는 예약입니다.")); reservations.remove(foundReservation); } diff --git a/src/test/java/roomescape/service/fakedao/FakeReservationDaoTest.java b/src/test/java/roomescape/service/fakedao/FakeReservationDaoTest.java new file mode 100644 index 0000000000..ef482c2657 --- /dev/null +++ b/src/test/java/roomescape/service/fakedao/FakeReservationDaoTest.java @@ -0,0 +1,147 @@ +package roomescape.service.fakedao; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import roomescape.repository.dto.ReservationSavedDto; + +import java.time.LocalDate; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.*; + +class FakeReservationDaoTest { + + private static final int INITIAL_RESERVATION_COUNT = 3; + private static final List INITIAL_RESERVATIONS = List.of( + new ReservationSavedDto(1, "n1", LocalDate.now(), 1, 1), + new ReservationSavedDto(2, "n2", LocalDate.now(), 1, 2), + new ReservationSavedDto(3, "n3", LocalDate.now(), 1, 3) + ); + + private FakeReservationDao fakeReservationDao; + + @BeforeEach + void setUp() { + fakeReservationDao = new FakeReservationDao(INITIAL_RESERVATIONS); + } + + @DisplayName("전체 예약을 조회한다.") + @Test + void should_find_all_reservations() { + List allReservations = fakeReservationDao.findAll(); + assertThat(allReservations).hasSize(INITIAL_RESERVATION_COUNT); + assertThat(allReservations).isEqualTo(INITIAL_RESERVATIONS); + } + + @DisplayName("예약을 저장한 후 id를 반환한다.") + @Test + void should_save_reservation_time() { + ReservationSavedDto reservationSavedDto = new ReservationSavedDto(4, "n4", LocalDate.now(), 1, 1); + long id = fakeReservationDao.save(reservationSavedDto); + assertThat(id).isEqualTo(INITIAL_RESERVATION_COUNT + 1); + assertThat(fakeReservationDao.findAll()).hasSize(INITIAL_RESERVATION_COUNT + 1); + } + + @DisplayName("특정 id를 가진 예약을 조회한다.") + @Test + void should_find_reservation_by_id() { + Optional time = fakeReservationDao.findById(1); + assertThat(time).hasValue(new ReservationSavedDto(1, "n1", LocalDate.now(), 1, 1)); + } + + @DisplayName("유효하지 않은 id를 가진 예약을 조회하려는 경우 빈 Optional 을 반환한다.") + @Test + void should_return_empty_optional_when_not_exist_id() { + Optional reservationSavedDto = fakeReservationDao.findById(999); + assertThat(reservationSavedDto).isEmpty(); + } + + @DisplayName("특정 날짜와 테마 id를 가진 예약을 조회한다.") + @Test + void should_find_reservations_by_date_and_themeId() { + List reservations = fakeReservationDao.findByDateAndThemeId(LocalDate.now(), 1); + assertThat(reservations).containsOnly(new ReservationSavedDto(1, "n1", LocalDate.now(), 1, 1)); + } + + @DisplayName("해당 날짜와 테마 id를 가진 예약이 없는 경우 빈 리스트를 반환한다.") + @Test + void should_return_empty_list_when_not_exist() { + List reservations = fakeReservationDao.findByDateAndThemeId(LocalDate.now(), 999); + assertThat(reservations).isEmpty(); + } + + @DisplayName("특정 날짜에 해당하는 예약의 테마 id를, 개수 순 -> 테마 id 순으로 정렬하여, 수를 추려 반환한다.") + @Test + void findThemeIdByDateAndOrderByThemeIdCountAndLimit() { + List themeIds = fakeReservationDao.findThemeIdByDateAndOrderByThemeIdCountAndLimit(LocalDate.of(2000, 1, 1), LocalDate.now(), 2); + assertThat(themeIds).containsExactly(1L, 2L); + } + + @DisplayName("예약을 삭제한다.") + @Test + void should_delete_reservation() { + fakeReservationDao.deleteById(1); + assertThat(fakeReservationDao.findById(1)).isEmpty(); + assertThat(fakeReservationDao.findAll()).hasSize(INITIAL_RESERVATION_COUNT - 1); + } + + @DisplayName("유효한 id를 가진 예약을 삭제하려는 경우 예외가 발생하지 않는다.") + @Test + void should_not_throw_exception_when_exist_id() { + assertThatCode(() -> fakeReservationDao.deleteById(1)) + .doesNotThrowAnyException(); + } + + @DisplayName("유효하지 않은 id를 가진 예약을 삭제하려는 경우 예외가 발생한다.") + @Test + void should_throw_exception_when_not_exist_id() { + assertThatThrownBy(() -> fakeReservationDao.deleteById(999)) + .isInstanceOf(NoSuchElementException.class) + .hasMessage("존재하지 않는 예약입니다."); + } + + @DisplayName("해당 id를 가진 예약 시간이 존재하면 참을 반환한다.") + @Test + void should_return_true_when_exist_id() { + Boolean isExist = fakeReservationDao.isExistById(1); + assertThat(isExist).isTrue(); + } + + @DisplayName("해당 id를 가진 예약 시간이 존재하지 않으면 거짓을 반환한다.") + @Test + void should_return_false_when_not_exist_id() { + Boolean isExist = fakeReservationDao.isExistById(999); + assertThat(isExist).isFalse(); + } + + @DisplayName("해당 timeId를 가진 예약이 존재하면 참을 반환한다.") + @Test + void should_return_true_when_exist_timeId() { + Boolean isExist = fakeReservationDao.isExistByTimeId(1); + assertThat(isExist).isTrue(); + } + + @DisplayName("해당 timeId를 가진 예약이 존재하지 않으면 거짓을 반환한다.") + @Test + void should_return_false_when_not_exist_timeId() { + Boolean isExist = fakeReservationDao.isExistByTimeId(999); + assertThat(isExist).isFalse(); + } + + @DisplayName("해당 날짜와 timeId를 가진 예약이 존재하면 참을 반환한다.") + @Test + void should_return_true_when_exist_date_and_timeId() { + Boolean isExist = fakeReservationDao.isExistByDateAndTimeId(LocalDate.now(), 1); + assertThat(isExist).isTrue(); + } + + @DisplayName("해당 날짜와 timeId를 가진 예약이 존재하지 않으면 거짓을 반환한다.") + @Test + void should_return_false_when_not_exist_date_and_timeId() { + Boolean isExist = fakeReservationDao.isExistByDateAndTimeId(LocalDate.now(), 999); + assertThat(isExist).isFalse(); + } +} \ No newline at end of file diff --git a/src/test/java/roomescape/service/fakedao/FakeReservationTimeDao.java b/src/test/java/roomescape/service/fakedao/FakeReservationTimeDao.java index 41ff6970f3..a02e491c73 100644 --- a/src/test/java/roomescape/service/fakedao/FakeReservationTimeDao.java +++ b/src/test/java/roomescape/service/fakedao/FakeReservationTimeDao.java @@ -43,7 +43,7 @@ public void deleteById(long id) { ReservationTime findReservationTime = reservationTimes.stream() .filter(reservationTime -> reservationTime.getId() == id) .findFirst() - .orElseThrow(() -> new NoSuchElementException("해당하는 아이디가 없습니다.")); + .orElseThrow(() -> new NoSuchElementException("존재하지 않는 예약 시간입니다.")); reservationTimes.remove(findReservationTime); } diff --git a/src/test/java/roomescape/service/fakedao/FakeReservationTimeDaoTest.java b/src/test/java/roomescape/service/fakedao/FakeReservationTimeDaoTest.java new file mode 100644 index 0000000000..bdeec04f12 --- /dev/null +++ b/src/test/java/roomescape/service/fakedao/FakeReservationTimeDaoTest.java @@ -0,0 +1,112 @@ +package roomescape.service.fakedao; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import roomescape.model.ReservationTime; + +import java.time.LocalTime; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.*; + +class FakeReservationTimeDaoTest { + + private static final int INITIAL_TIME_COUNT = 3; + private static final List INITIAL_TIMES = List.of( + new ReservationTime(1, LocalTime.of(1, 0)), + new ReservationTime(2, LocalTime.of(2, 0)), + new ReservationTime(3, LocalTime.of(3, 0)) + ); + + private FakeReservationTimeDao fakeReservationTimeDao; + + @BeforeEach + void setUp() { + fakeReservationTimeDao = new FakeReservationTimeDao(INITIAL_TIMES); + } + + @DisplayName("예약 시간을 저장한 후 id를 반환한다.") + @Test + void should_save_reservation_time() { + ReservationTime time = new ReservationTime(4, LocalTime.of(4, 0)); + long id = fakeReservationTimeDao.save(time); + assertThat(id).isEqualTo(INITIAL_TIME_COUNT + 1); + assertThat(fakeReservationTimeDao.findAll()).hasSize(INITIAL_TIME_COUNT + 1); + } + + @DisplayName("전체 예약 시간을 조회한다.") + @Test + void should_find_all_reservation_times() { + List allTimes = fakeReservationTimeDao.findAll(); + assertThat(allTimes).hasSize(INITIAL_TIME_COUNT); + assertThat(allTimes).isEqualTo(INITIAL_TIMES); + } + + @DisplayName("특정 id를 가진 예약 시간을 조회한다.") + @Test + void should_find_reservation_time_by_id() { + Optional time = fakeReservationTimeDao.findById(1); + assertThat(time).hasValue(new ReservationTime(1, LocalTime.of(1, 0))); + } + + @DisplayName("유효하지 않은 id를 가진 예약 시간을 조회하려는 경우 빈 Optional 을 반환한다.") + @Test + void should_return_empty_optional_when_not_exist_id() { + Optional time = fakeReservationTimeDao.findById(999); + assertThat(time).isEmpty(); + } + + @DisplayName("예약 시간을 삭제한다.") + @Test + void should_delete_reservation_time() { + fakeReservationTimeDao.deleteById(1); + assertThat(fakeReservationTimeDao.findById(1)).isEmpty(); + assertThat(fakeReservationTimeDao.findAll()).hasSize(INITIAL_TIME_COUNT - 1); + } + + @DisplayName("유효한 id를 가진 예약 시간을 삭제하려는 경우 예외가 발생하지 않는다.") + @Test + void should_not_throw_exception_when_exist_id() { + assertThatCode(() -> fakeReservationTimeDao.deleteById(1)) + .doesNotThrowAnyException(); + } + + @DisplayName("유효하지 않은 id를 가진 예약 시간을 삭제하려는 경우 예외가 발생한다.") + @Test + void should_throw_exception_when_not_exist_id() { + assertThatThrownBy(() -> fakeReservationTimeDao.deleteById(999)) + .isInstanceOf(NoSuchElementException.class) + .hasMessage("존재하지 않는 예약 시간입니다."); + } + + @DisplayName("해당 id를 가진 예약 시간이 존재하면 참을 반환한다.") + @Test + void should_return_true_when_exist_id() { + Boolean isExist = fakeReservationTimeDao.isExistById(1); + assertThat(isExist).isTrue(); + } + + @DisplayName("해당 id를 가진 예약 시간이 존재하지 않으면 거짓을 반환한다.") + @Test + void should_return_false_when_not_exist_id() { + Boolean isExist = fakeReservationTimeDao.isExistById(999); + assertThat(isExist).isFalse(); + } + + @DisplayName("해당 startAt을 가진 예약 시간이 존재하면 참을 반환한다.") + @Test + void should_return_true_when_exist_startAt() { + Boolean isExist = fakeReservationTimeDao.isExistByStartAt(LocalTime.of(1, 0)); + assertThat(isExist).isTrue(); + } + + @DisplayName("해당 startAt을 가진 예약 시간이 존재하지 않으면 거짓을 반환한다.") + @Test + void should_return_false_when_not_exist_startAt() { + Boolean isExist = fakeReservationTimeDao.isExistByStartAt(LocalTime.of(9, 0)); + assertThat(isExist).isFalse(); + } +} \ No newline at end of file diff --git a/src/test/java/roomescape/service/fakedao/FakeThemeDaoTest.java b/src/test/java/roomescape/service/fakedao/FakeThemeDaoTest.java new file mode 100644 index 0000000000..96ae46303e --- /dev/null +++ b/src/test/java/roomescape/service/fakedao/FakeThemeDaoTest.java @@ -0,0 +1,83 @@ +package roomescape.service.fakedao; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import roomescape.model.Theme; + +import java.util.List; +import java.util.NoSuchElementException; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.*; + +class FakeThemeDaoTest { + + private static final int INITIAL_THEME_COUNT = 3; + private static final List INITIAL_THEMES = List.of( + new Theme(1, "n1", "d1", "t1"), + new Theme(2, "n2", "d2", "t2"), + new Theme(3, "n3", "d3", "t3") + ); + + private FakeThemeDao fakeThemeDao; + + @BeforeEach + void setUp() { + fakeThemeDao = new FakeThemeDao(INITIAL_THEMES); + } + + @DisplayName("전체 테마를 조회한다.") + @Test + void should_find_all_themes() { + List allThemes = fakeThemeDao.findAll(); + assertThat(allThemes).hasSize(INITIAL_THEME_COUNT); + assertThat(allThemes).isEqualTo(INITIAL_THEMES); + } + + @DisplayName("테마를 저장한 후 id를 반환한다.") + @Test + void should_save_theme() { + Theme theme = new Theme(4, "n4", "d4", "t4"); + long id = fakeThemeDao.save(theme); + assertThat(id).isEqualTo(INITIAL_THEME_COUNT + 1); + assertThat(fakeThemeDao.findAll()).hasSize(INITIAL_THEME_COUNT + 1); + } + + @DisplayName("특정 id를 가진 테마를 조회한다.") + @Test + void should_find_theme_by_id() { + Optional theme = fakeThemeDao.findById(1); + assertThat(theme).hasValue(new Theme(1, "n1", "d1", "t1")); + } + + @DisplayName("유효하지 않은 id를 가진 테마를 조회하려는 경우 빈 Optional 을 반환한다.") + @Test + void should_return_empty_optional_when_not_exist_id() { + Optional theme = fakeThemeDao.findById(999); + assertThat(theme).isEmpty(); + } + + @DisplayName("테마를 삭제한다.") + @Test + void should_delete_theme() { + fakeThemeDao.deleteById(1); + assertThat(fakeThemeDao.findById(1)).isEmpty(); + assertThat(fakeThemeDao.findAll()).hasSize(INITIAL_THEME_COUNT - 1); + } + + @DisplayName("유효한 id를 가진 테마를 삭제하려는 경우 예외가 발생하지 않는다.") + @Test + void should_not_throw_exception_when_exist_id() { + assertThatCode(() -> fakeThemeDao.deleteById(1)) + .doesNotThrowAnyException(); + } + + @DisplayName("유효하지 않은 id를 가진 테마를 삭제하려는 경우 예외가 발생한다.") + @Test + void should_throw_exception_when_not_exist_id() { + assertThatThrownBy(() -> fakeThemeDao.deleteById(999)) + .isInstanceOf(NoSuchElementException.class) + .hasMessage("존재하지 않는 테마입니다."); + } +} \ No newline at end of file From 2bf9a5d1ae91e6aa2da232a0dabd2e1757815ce0 Mon Sep 17 00:00:00 2001 From: SCY Date: Tue, 7 May 2024 00:31:21 +0900 Subject: [PATCH 61/74] =?UTF-8?q?fix(controller):=20=EC=9A=94=EC=B2=AD=20?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=84=B0=EC=97=90=20=EB=8C=80=ED=95=B4=20nul?= =?UTF-8?q?l=20=EA=B0=92=20=ED=97=88=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/ReservationController.java | 4 ++-- .../controller/ReservationTimeController.java | 3 ++- .../roomescape/controller/ThemeController.java | 2 +- .../controller/request/ReservationRequest.java | 10 +++++----- .../repository/ReservationRepository.java | 2 -- .../roomescape/service/ReservationService.java | 13 +++++++++++-- .../service/ReservationTimeService.java | 15 +++++++++++---- .../java/roomescape/service/ThemeService.java | 5 ++++- .../service/ReservationServiceTest.java | 8 ++++---- .../service/ReservationTimeServiceTest.java | 8 ++++---- .../java/roomescape/service/ThemeServiceTest.java | 2 +- 11 files changed, 45 insertions(+), 27 deletions(-) diff --git a/src/main/java/roomescape/controller/ReservationController.java b/src/main/java/roomescape/controller/ReservationController.java index 7c3ef5613c..38f112b227 100644 --- a/src/main/java/roomescape/controller/ReservationController.java +++ b/src/main/java/roomescape/controller/ReservationController.java @@ -43,7 +43,7 @@ public ResponseEntity addReservation(@RequestBody Reservati } @DeleteMapping("/{id}") - public ResponseEntity deleteReservation(@PathVariable("id") long id) { + public ResponseEntity deleteReservation(@PathVariable("id") Long id) { reservationService.deleteReservation(id); return ResponseEntity.noContent().build(); } @@ -51,7 +51,7 @@ public ResponseEntity deleteReservation(@PathVariable("id") long id) { @GetMapping("/times") public ResponseEntity> showReservationTimesInformation( @RequestParam(name = "date") LocalDate date, - @RequestParam(name = "themeId") long themeId) { + @RequestParam(name = "themeId") Long themeId) { List response = reservationService.findReservationTimesInformation(date, themeId); // TODO: 여기서 response 객체로 반환하도록 수정 return ResponseEntity.ok(response); diff --git a/src/main/java/roomescape/controller/ReservationTimeController.java b/src/main/java/roomescape/controller/ReservationTimeController.java index 604393ea73..e5f2fc0e5e 100644 --- a/src/main/java/roomescape/controller/ReservationTimeController.java +++ b/src/main/java/roomescape/controller/ReservationTimeController.java @@ -4,6 +4,7 @@ import org.springframework.web.bind.annotation.*; import roomescape.controller.request.ReservationTimeRequest; import roomescape.controller.response.ReservationTimeResponse; +import roomescape.exception.BadRequestException; import roomescape.model.ReservationTime; import roomescape.service.ReservationTimeService; import roomescape.service.dto.ReservationTimeDto; @@ -41,7 +42,7 @@ public ResponseEntity addReservationTime(@RequestBody R } @DeleteMapping("/{id}") - public ResponseEntity deleteReservationTime(@PathVariable("id") long id) { + public ResponseEntity deleteReservationTime(@PathVariable("id") Long id) { reservationTimeService.deleteReservationTime(id); return ResponseEntity.noContent().build(); } diff --git a/src/main/java/roomescape/controller/ThemeController.java b/src/main/java/roomescape/controller/ThemeController.java index 0f2639f17d..847955d1bb 100644 --- a/src/main/java/roomescape/controller/ThemeController.java +++ b/src/main/java/roomescape/controller/ThemeController.java @@ -41,7 +41,7 @@ public ResponseEntity addTheme(@RequestBody ThemeRequest request) } @DeleteMapping("/{id}") - public ResponseEntity deleteTheme(@PathVariable(name = "id") long id) { + public ResponseEntity deleteTheme(@PathVariable("id") Long id) { themeService.deleteTheme(id); return ResponseEntity.noContent().build(); } diff --git a/src/main/java/roomescape/controller/request/ReservationRequest.java b/src/main/java/roomescape/controller/request/ReservationRequest.java index adef18958a..1995c3b253 100644 --- a/src/main/java/roomescape/controller/request/ReservationRequest.java +++ b/src/main/java/roomescape/controller/request/ReservationRequest.java @@ -12,22 +12,22 @@ public class ReservationRequest { private final long themeId; public ReservationRequest(String name, LocalDate date, Long timeId, Long themeId) { - validateName(name); validateNull(date, timeId, themeId); + validateName(name); this.name = name; this.date = date; this.timeId = timeId; this.themeId = themeId; } - private void validateName(String name) { - if (name == null || name.isEmpty()) { + private void validateNull(LocalDate date, Long timeId, Long themeId) { + if (date == null || timeId == null || themeId == null) { throw new BadRequestException("[ERROR] 유효하지 않은 요청입니다."); } } - private void validateNull(LocalDate date, Long timeId, Long themeId) { - if (date == null || timeId == null || themeId == null) { + private void validateName(String name) { + if (name == null || name.isEmpty()) { throw new BadRequestException("[ERROR] 유효하지 않은 요청입니다."); } } diff --git a/src/main/java/roomescape/repository/ReservationRepository.java b/src/main/java/roomescape/repository/ReservationRepository.java index b9899239aa..2fc4385851 100644 --- a/src/main/java/roomescape/repository/ReservationRepository.java +++ b/src/main/java/roomescape/repository/ReservationRepository.java @@ -54,9 +54,7 @@ public Reservation saveReservation(Reservation reservation) { reservation.getId(), reservation.getName(), reservation.getDate(), reservation.getTime().getId(), reservation.getTheme().getId()); long id = reservationDao.save(reservationSavedDto); - System.out.println(id); ReservationSavedDto saved = reservationDao.findById(id).orElseThrow(NoSuchElementException::new); - System.out.println("@@" + saved.getId()); ReservationTime time = reservationTimeDao.findById(saved.getTimeId()).orElseThrow(NoSuchElementException::new); Theme theme = themeDao.findById(saved.getThemeId()).orElseThrow(NoSuchElementException::new); return new Reservation(id, saved.getName(), saved.getDate(), time, theme); diff --git a/src/main/java/roomescape/service/ReservationService.java b/src/main/java/roomescape/service/ReservationService.java index 4147d12119..1fcbfc386f 100644 --- a/src/main/java/roomescape/service/ReservationService.java +++ b/src/main/java/roomescape/service/ReservationService.java @@ -66,11 +66,18 @@ private void validateDuplication(LocalDate date, long timeId) { } } - public void deleteReservation(long id) { + public void deleteReservation(Long id) { + validateNull(id); validateExistence(id); reservationRepository.deleteReservationById(id); } + private void validateNull(Long id) { + if (id == null) { + throw new BadRequestException("[ERROR] id에 null이 입력될 수 없습니다."); + } + } + private void validateExistence(long id) { boolean isNotExist = !reservationRepository.isExistReservationById(id); if (isNotExist) { @@ -78,7 +85,9 @@ private void validateExistence(long id) { } } - public List findReservationTimesInformation(LocalDate date, long themeId) { + public List findReservationTimesInformation(LocalDate date, Long themeId) { + // TODO: themeId <= 0 예외 처리 + validateNull(themeId); List bookedTimes = reservationRepository.findReservationTimeBooked(date, themeId); List notBookedTimes = reservationRepository.findReservationTimeNotBooked(date, themeId); List bookedResponse = mapToResponse(bookedTimes, true); diff --git a/src/main/java/roomescape/service/ReservationTimeService.java b/src/main/java/roomescape/service/ReservationTimeService.java index 8c5f306dd9..0b829d8e30 100644 --- a/src/main/java/roomescape/service/ReservationTimeService.java +++ b/src/main/java/roomescape/service/ReservationTimeService.java @@ -44,24 +44,31 @@ public ReservationTime findReservationTime(long id) { .orElseThrow(() -> new BadRequestException("[ERROR] 데이터가 저장되지 않습니다.")); } - public void deleteReservationTime(long id) { + public void deleteReservationTime(Long id) { validate(id); reservationTimeRepository.deleteReservationTimeById(id); } - private void validate(long id) { + private void validate(Long id) { + validateNull(id); validateExistence(id); validateDependence(id); } - private void validateDependence(long id) { + private void validateNull(Long id) { + if (id == null) { + throw new BadRequestException("[ERROR] id에 null이 입력될 수 없습니다."); + } + } + + private void validateDependence(Long id) { boolean isExist = reservationTimeRepository.isExistReservationByTimeId(id); if (isExist) { throw new BadRequestException("[ERROR] 해당 시간을 사용하고 있는 예약이 있습니다."); } } - private void validateExistence(long id) { + private void validateExistence(Long id) { boolean isNotExist = !reservationTimeRepository.isExistReservationTimeById(id); if (isNotExist) { throw new NotFoundException("[ERROR] 존재하지 않는 시간입니다."); diff --git a/src/main/java/roomescape/service/ThemeService.java b/src/main/java/roomescape/service/ThemeService.java index 8bffd55f65..4a09a205a1 100644 --- a/src/main/java/roomescape/service/ThemeService.java +++ b/src/main/java/roomescape/service/ThemeService.java @@ -31,7 +31,10 @@ public Theme saveTheme(ThemeDto themeDto) { .orElseThrow(() -> new BadRequestException("[ERROR] 데이터가 저장되지 않습니다.")); } - public void deleteTheme(long id) { + public void deleteTheme(Long id) { + if (id == null) { + throw new BadRequestException("[ERROR] id에 null이 입력될 수 없습니다."); + } themeRepository.deleteThemeById(id); } diff --git a/src/test/java/roomescape/service/ReservationServiceTest.java b/src/test/java/roomescape/service/ReservationServiceTest.java index 8627d7c669..3bb42735ec 100644 --- a/src/test/java/roomescape/service/ReservationServiceTest.java +++ b/src/test/java/roomescape/service/ReservationServiceTest.java @@ -70,21 +70,21 @@ void should_save_reservation() { @DisplayName("예약을 삭제한다.") @Test void should_delete_reservation() { - reservationService.deleteReservation(1); + reservationService.deleteReservation(1L); assertThat(reservationService.findAllReservations()).hasSize(INITIAL_RESERVATION_COUNT - 1); } @DisplayName("존재하는 예약을 삭제하려 하면 예외가 발생하지 않는다.") @Test void should_not_throw_exception_when_exist_reservation_time() { - assertThatCode(() -> reservationService.deleteReservation(1)) + assertThatCode(() -> reservationService.deleteReservation(1L)) .doesNotThrowAnyException(); } @DisplayName("존재하지 않는 예약을 삭제하려 하면 예외가 발생한다.") @Test void should_throw_exception_when_not_exist_reservation_time() { - assertThatThrownBy(() -> reservationService.deleteReservation(999)) + assertThatThrownBy(() -> reservationService.deleteReservation(999L)) .isInstanceOf(NotFoundException.class) .hasMessage("[ERROR] 존재하지 않는 예약입니다."); } @@ -127,7 +127,7 @@ void should_throw_exception_when_add_exist_reservation() { @Test void should_return_times_with_book_state() { LocalDate date = LocalDate.of(9999, 9, 9); - List times = reservationService.findReservationTimesInformation(date, 1); + List times = reservationService.findReservationTimesInformation(date, 1L); assertThat(times).hasSize(INITIAL_TIME_COUNT); assertThat(times).containsOnly( new MemberReservationTimeResponse(1, LocalTime.of(1, 0), true), diff --git a/src/test/java/roomescape/service/ReservationTimeServiceTest.java b/src/test/java/roomescape/service/ReservationTimeServiceTest.java index 9b0a061dad..c1499a3be6 100644 --- a/src/test/java/roomescape/service/ReservationTimeServiceTest.java +++ b/src/test/java/roomescape/service/ReservationTimeServiceTest.java @@ -66,21 +66,21 @@ void should_save_reservation_time() { @DisplayName("예약 시간을 삭제한다.") @Test void should_delete_reservation_time() { - reservationTimeService.deleteReservationTime(3); + reservationTimeService.deleteReservationTime(3L); assertThat(reservationTimeService.findAllReservationTimes()).hasSize(INITIAL_TIME_COUNT - 1); } @DisplayName("예약 시간을 삭제하려 할 때 특정 id를 가진 예약 시간이 존재하는 경우 예외가 발생하지 않는다.") @Test void should_not_throw_exception_when_exist_id() { - assertThatCode(() -> reservationTimeService.deleteReservationTime(3)) + assertThatCode(() -> reservationTimeService.deleteReservationTime(3L)) .doesNotThrowAnyException(); } @DisplayName("예약 시간을 삭제하려 할 때 특정 id를 가진 예약 시간이 존재하지 않는 경우 예외가 발생한다.") @Test void should_throw_exception_when_not_exist_id() { - assertThatThrownBy(() -> reservationTimeService.deleteReservationTime(999)) + assertThatThrownBy(() -> reservationTimeService.deleteReservationTime(999L)) .isInstanceOf(NotFoundException.class) .hasMessage("[ERROR] 존재하지 않는 시간입니다."); } @@ -88,7 +88,7 @@ void should_throw_exception_when_not_exist_id() { @DisplayName("예약 시간을 삭제하려 할 때 해당 시간을 사용하는 예약이 존재하는 경우 예외가 발생한다.") @Test void should_throw_exception_when_exist_reservation_using_time() { - assertThatThrownBy(() -> reservationTimeService.deleteReservationTime(2)) + assertThatThrownBy(() -> reservationTimeService.deleteReservationTime(2L)) .isInstanceOf(BadRequestException.class) .hasMessage("[ERROR] 해당 시간을 사용하고 있는 예약이 있습니다."); } diff --git a/src/test/java/roomescape/service/ThemeServiceTest.java b/src/test/java/roomescape/service/ThemeServiceTest.java index 9274c69899..b3d3de0a47 100644 --- a/src/test/java/roomescape/service/ThemeServiceTest.java +++ b/src/test/java/roomescape/service/ThemeServiceTest.java @@ -53,7 +53,7 @@ void should_save_theme() { @DisplayName("테마를 삭제한다.") @Test void should_delete_theme() { - themeService.deleteTheme(1); + themeService.deleteTheme(1L); assertThat(themeService.findAllThemes()).hasSize(INITIAL_THEME_COUNT - 1); } From b619d2f6560e97b527a065f7a118c55fed007555 Mon Sep 17 00:00:00 2001 From: SCY Date: Tue, 7 May 2024 01:11:18 +0900 Subject: [PATCH 62/74] =?UTF-8?q?fix(GlobalExceptionHandler):=20=EB=AA=A8?= =?UTF-8?q?=EB=93=A0=20=EB=9F=B0=ED=83=80=EC=9E=84=20=EC=98=88=EC=99=B8=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/roomescape/exception/GlobalExceptionHandler.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/roomescape/exception/GlobalExceptionHandler.java b/src/main/java/roomescape/exception/GlobalExceptionHandler.java index 488e143ac5..6ab880bf78 100644 --- a/src/main/java/roomescape/exception/GlobalExceptionHandler.java +++ b/src/main/java/roomescape/exception/GlobalExceptionHandler.java @@ -16,7 +16,7 @@ public ResponseEntity handleNotFoundException(NotFoundException exceptio } @ExceptionHandler(value = {BadRequestException.class, DuplicatedException.class}) - public ResponseEntity handleBadRequestException(RuntimeException exception) { + public ResponseEntity handleBadRequestAndDuplicatedException(RuntimeException exception) { return new ResponseEntity<>(exception.getMessage(), HttpStatus.BAD_REQUEST); } @@ -24,4 +24,9 @@ public ResponseEntity handleBadRequestException(RuntimeException excepti public ResponseEntity handleDateTimeParseException(DateTimeParseException exception) { return new ResponseEntity<>("[ERROR] 유효하지 않은 요청입니다.", HttpStatus.BAD_REQUEST); } + + @ExceptionHandler(value = RuntimeException.class) + public ResponseEntity handleRuntimeException(RuntimeException exception) { + return new ResponseEntity<>(exception.getMessage(), HttpStatus.NOT_FOUND); + } } From b6d69bff3ba7e4c3e750ae9aa87a9b73c7732fa1 Mon Sep 17 00:00:00 2001 From: SCY Date: Tue, 7 May 2024 01:12:12 +0900 Subject: [PATCH 63/74] =?UTF-8?q?refactor(model):=20toString=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=20=EC=84=A0=EC=96=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/roomescape/model/Reservation.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/main/java/roomescape/model/Reservation.java b/src/main/java/roomescape/model/Reservation.java index 4afe13c038..fc18962493 100644 --- a/src/main/java/roomescape/model/Reservation.java +++ b/src/main/java/roomescape/model/Reservation.java @@ -61,4 +61,15 @@ public boolean equals(Object o) { public int hashCode() { return Objects.hash(id, name, date, time, theme); } + + @Override + public String toString() { + return "Reservation{" + + "id=" + id + + ", name='" + name + '\'' + + ", date=" + date + + ", time=" + time + + ", theme=" + theme + + '}'; + } } From d1dc05eb3af4c0e9993ad579af62fbfabd2252e6 Mon Sep 17 00:00:00 2001 From: SCY Date: Tue, 7 May 2024 01:13:05 +0900 Subject: [PATCH 64/74] =?UTF-8?q?refactor(MemberReservationTimeResponse):?= =?UTF-8?q?=20equals&hashCode=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../response/MemberReservationTimeResponse.java | 14 -------------- .../roomescape/service/ReservationService.java | 8 ++++---- .../controller/ReservationControllerTest.java | 17 +++++++---------- .../service/ReservationServiceTest.java | 9 +++------ 4 files changed, 14 insertions(+), 34 deletions(-) diff --git a/src/main/java/roomescape/controller/response/MemberReservationTimeResponse.java b/src/main/java/roomescape/controller/response/MemberReservationTimeResponse.java index 7a379c097b..f2d655a7ae 100644 --- a/src/main/java/roomescape/controller/response/MemberReservationTimeResponse.java +++ b/src/main/java/roomescape/controller/response/MemberReservationTimeResponse.java @@ -1,7 +1,6 @@ package roomescape.controller.response; import java.time.LocalTime; -import java.util.Objects; public class MemberReservationTimeResponse { @@ -26,17 +25,4 @@ public LocalTime getStartAt() { public boolean getIsBooked() { return isBooked; } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - MemberReservationTimeResponse that = (MemberReservationTimeResponse) o; - return timeId == that.timeId && isBooked == that.isBooked && Objects.equals(startAt, that.startAt); - } - - @Override - public int hashCode() { - return Objects.hash(timeId, startAt, isBooked); - } } diff --git a/src/main/java/roomescape/service/ReservationService.java b/src/main/java/roomescape/service/ReservationService.java index 1fcbfc386f..e608f9d0e9 100644 --- a/src/main/java/roomescape/service/ReservationService.java +++ b/src/main/java/roomescape/service/ReservationService.java @@ -92,7 +92,7 @@ public List findReservationTimesInformation(Local List notBookedTimes = reservationRepository.findReservationTimeNotBooked(date, themeId); List bookedResponse = mapToResponse(bookedTimes, true); List notBookedResponse = mapToResponse(notBookedTimes, false); - return concat(notBookedResponse, bookedResponse); + return concat(bookedResponse, notBookedResponse); } private List mapToResponse(List times, boolean isBooked) { @@ -101,8 +101,8 @@ private List mapToResponse(List .toList(); } - private List concat(List notBookedTimes, - List bookedTimes) { - return Stream.concat(notBookedTimes.stream(), bookedTimes.stream()).toList(); + private List concat(List first, + List second) { + return Stream.concat(first.stream(), second.stream()).toList(); } } diff --git a/src/test/java/roomescape/controller/ReservationControllerTest.java b/src/test/java/roomescape/controller/ReservationControllerTest.java index 4fd5ddf2dc..29338089df 100644 --- a/src/test/java/roomescape/controller/ReservationControllerTest.java +++ b/src/test/java/roomescape/controller/ReservationControllerTest.java @@ -15,7 +15,6 @@ import roomescape.controller.response.ReservationResponse; import java.time.LocalDate; -import java.time.LocalTime; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -135,22 +134,20 @@ void should_delete_reservation_when_reservation_exist() { @DisplayName("특정 날짜와 테마에 따른 모든 시간의 예약 가능 여부를 확인한다.") @Test void should_get_reservations_with_book_state_by_date_and_theme() { - String date = LocalDate.now().minusDays(1).toString(); // LD 으로 바꾸어보자! + String date = LocalDate.now().minusDays(1).toString(); long themeId = 1; List times = RestAssured.given().log().all() .when().get(String.format("/reservations/times?date=%s&themeId=%d", date, themeId)) .then().log().all() .statusCode(200) .extract().jsonPath().getList(".", MemberReservationTimeResponse.class); - System.out.println(times); + assertThat(times).hasSize(INITIAL_TIME_COUNT); - assertThat(times).containsOnly( - new MemberReservationTimeResponse(1, LocalTime.of(1, 0), true), - new MemberReservationTimeResponse(2, LocalTime.of(2, 0), true), - new MemberReservationTimeResponse(3, LocalTime.of(3, 0), false), - new MemberReservationTimeResponse(4, LocalTime.of(4, 0), false), - new MemberReservationTimeResponse(5, LocalTime.of(5, 0), false) - ); + assertThat(times.get(0).getIsBooked()).isTrue(); + assertThat(times.get(1).getIsBooked()).isTrue(); + assertThat(times.get(2).getIsBooked()).isFalse(); + assertThat(times.get(3).getIsBooked()).isFalse(); + assertThat(times.get(4).getIsBooked()).isFalse(); } private Integer countAllReservations() { diff --git a/src/test/java/roomescape/service/ReservationServiceTest.java b/src/test/java/roomescape/service/ReservationServiceTest.java index 3bb42735ec..0f2719e5a7 100644 --- a/src/test/java/roomescape/service/ReservationServiceTest.java +++ b/src/test/java/roomescape/service/ReservationServiceTest.java @@ -22,7 +22,6 @@ import java.time.LocalDate; import java.time.LocalTime; -import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.List; @@ -128,11 +127,9 @@ void should_throw_exception_when_add_exist_reservation() { void should_return_times_with_book_state() { LocalDate date = LocalDate.of(9999, 9, 9); List times = reservationService.findReservationTimesInformation(date, 1L); + assertThat(times).hasSize(INITIAL_TIME_COUNT); - assertThat(times).containsOnly( - new MemberReservationTimeResponse(1, LocalTime.of(1, 0), true), - new MemberReservationTimeResponse(2, LocalTime.of(2, 0), false), - new MemberReservationTimeResponse(3, LocalTime.now().truncatedTo(ChronoUnit.SECONDS), false) - ); + assertThat(times.get(0).getIsBooked()).isTrue(); + assertThat(times.get(1).getIsBooked()).isFalse(); } } From 4967160fb79652373cae12018681a2244b35555f Mon Sep 17 00:00:00 2001 From: SCY Date: Tue, 7 May 2024 01:13:17 +0900 Subject: [PATCH 65/74] =?UTF-8?q?style(all):=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20import=EB=AC=B8=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/roomescape/controller/ReservationTimeController.java | 1 - src/main/java/roomescape/repository/dao/JdbcReservationDao.java | 1 - src/main/java/roomescape/repository/dao/ReservationDao.java | 1 - 3 files changed, 3 deletions(-) diff --git a/src/main/java/roomescape/controller/ReservationTimeController.java b/src/main/java/roomescape/controller/ReservationTimeController.java index e5f2fc0e5e..c4b3334176 100644 --- a/src/main/java/roomescape/controller/ReservationTimeController.java +++ b/src/main/java/roomescape/controller/ReservationTimeController.java @@ -4,7 +4,6 @@ import org.springframework.web.bind.annotation.*; import roomescape.controller.request.ReservationTimeRequest; import roomescape.controller.response.ReservationTimeResponse; -import roomescape.exception.BadRequestException; import roomescape.model.ReservationTime; import roomescape.service.ReservationTimeService; import roomescape.service.dto.ReservationTimeDto; diff --git a/src/main/java/roomescape/repository/dao/JdbcReservationDao.java b/src/main/java/roomescape/repository/dao/JdbcReservationDao.java index a4a6d75726..bd041fe2af 100644 --- a/src/main/java/roomescape/repository/dao/JdbcReservationDao.java +++ b/src/main/java/roomescape/repository/dao/JdbcReservationDao.java @@ -3,7 +3,6 @@ import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.simple.SimpleJdbcInsert; import org.springframework.stereotype.Repository; -import roomescape.model.Reservation; import roomescape.repository.dto.ReservationSavedDto; import java.time.LocalDate; diff --git a/src/main/java/roomescape/repository/dao/ReservationDao.java b/src/main/java/roomescape/repository/dao/ReservationDao.java index 6088ebc59a..4085a6b509 100644 --- a/src/main/java/roomescape/repository/dao/ReservationDao.java +++ b/src/main/java/roomescape/repository/dao/ReservationDao.java @@ -1,6 +1,5 @@ package roomescape.repository.dao; -import roomescape.model.Reservation; import roomescape.repository.dto.ReservationSavedDto; import java.time.LocalDate; From a900183546f25a84bf8a7572dbde72bf6709c674 Mon Sep 17 00:00:00 2001 From: SCY Date: Tue, 7 May 2024 01:17:05 +0900 Subject: [PATCH 66/74] =?UTF-8?q?refactor(sql):=20=EB=8D=94=EB=AF=B8?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EC=83=9D=EC=84=B1=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=ED=8C=8C=EC=9D=BC=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/data.sql | 5 +++++ src/main/resources/schema.sql | 10 ++-------- 2 files changed, 7 insertions(+), 8 deletions(-) create mode 100644 src/main/resources/data.sql diff --git a/src/main/resources/data.sql b/src/main/resources/data.sql new file mode 100644 index 0000000000..49c5359c27 --- /dev/null +++ b/src/main/resources/data.sql @@ -0,0 +1,5 @@ +INSERT INTO reservation_time (start_at) VALUES ('10:00'); +INSERT INTO reservation_time (start_at) VALUES ('11:00'); + +INSERT INTO theme (name, description, thumbnail) VALUES ('에버', '공포', 'https://i.pinimg.com/236x/6e/bc/46/6ebc461a94a49f9ea3b8bbe2204145d4.jpg'); +INSERT INTO theme (name, description, thumbnail) VALUES ('배키', '스릴러', 'https://i.pinimg.com/236x/6e/bc/46/6ebc461a94a49f9ea3b8bbe2204145d4.jpg'); diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql index 3ea97e872c..99a882e1ba 100644 --- a/src/main/resources/schema.sql +++ b/src/main/resources/schema.sql @@ -20,14 +20,8 @@ CREATE TABLE reservation name VARCHAR(255) NOT NULL, date VARCHAR(255) NOT NULL, time_id BIGINT, - theme_id BIGINT, -- 컬럼 추가 + theme_id BIGINT, PRIMARY KEY (id), FOREIGN KEY (time_id) REFERENCES reservation_time (id), - FOREIGN KEY (theme_id) REFERENCES theme (id) -- 외래키 추가 + FOREIGN KEY (theme_id) REFERENCES theme (id) ); - -INSERT INTO reservation_time (start_at) VALUES ('10:00'); -INSERT INTO reservation_time (start_at) VALUES ('11:00'); - -INSERT INTO theme (name, description, thumbnail) VALUES ('에버', '공포', 'https://i.pinimg.com/236x/6e/bc/46/6ebc461a94a49f9ea3b8bbe2204145d4.jpg'); -INSERT INTO theme (name, description, thumbnail) VALUES ('배키', '스릴러', 'https://i.pinimg.com/236x/6e/bc/46/6ebc461a94a49f9ea3b8bbe2204145d4.jpg'); From d21c7275942fde72c394b10088b6ed91e964b808 Mon Sep 17 00:00:00 2001 From: SCY Date: Tue, 7 May 2024 01:19:57 +0900 Subject: [PATCH 67/74] =?UTF-8?q?refactor(response):=20=EB=B8=8C=EB=9D=BC?= =?UTF-8?q?=EC=9A=B0=EC=A0=80=EC=97=90=20=EB=B0=98=ED=99=98=ED=95=98?= =?UTF-8?q?=EB=8A=94=20=EC=8B=9C=EA=B0=84=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20?= =?UTF-8?q?=ED=8F=AC=EB=A7=B7=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/response/MemberReservationTimeResponse.java | 3 +++ .../controller/response/ReservationTimeResponse.java | 2 ++ 2 files changed, 5 insertions(+) diff --git a/src/main/java/roomescape/controller/response/MemberReservationTimeResponse.java b/src/main/java/roomescape/controller/response/MemberReservationTimeResponse.java index f2d655a7ae..979ff0d156 100644 --- a/src/main/java/roomescape/controller/response/MemberReservationTimeResponse.java +++ b/src/main/java/roomescape/controller/response/MemberReservationTimeResponse.java @@ -1,5 +1,7 @@ package roomescape.controller.response; +import com.fasterxml.jackson.annotation.JsonFormat; + import java.time.LocalTime; public class MemberReservationTimeResponse { @@ -18,6 +20,7 @@ public long getTimeId() { return timeId; } + @JsonFormat(pattern = "HH:mm") public LocalTime getStartAt() { return startAt; } diff --git a/src/main/java/roomescape/controller/response/ReservationTimeResponse.java b/src/main/java/roomescape/controller/response/ReservationTimeResponse.java index 5c7aab672c..4db52a78f9 100644 --- a/src/main/java/roomescape/controller/response/ReservationTimeResponse.java +++ b/src/main/java/roomescape/controller/response/ReservationTimeResponse.java @@ -1,5 +1,6 @@ package roomescape.controller.response; +import com.fasterxml.jackson.annotation.JsonFormat; import roomescape.model.ReservationTime; import java.time.LocalTime; @@ -22,6 +23,7 @@ public long getId() { return id; } + @JsonFormat(pattern = "HH:mm") public LocalTime getStartAt() { return startAt; } From ce753ce71266995ee97365b493f1038d35f0273e Mon Sep 17 00:00:00 2001 From: SCY Date: Tue, 7 May 2024 01:30:37 +0900 Subject: [PATCH 68/74] =?UTF-8?q?refactor(request):=20=EC=9A=94=EC=B2=AD?= =?UTF-8?q?=EB=90=9C=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EA=B2=80=EC=A6=9D=20?= =?UTF-8?q?=EA=B5=AC=EC=B2=B4=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../request/ReservationRequest.java | 20 +++-- .../request/ReservationTimeRequest.java | 6 +- .../controller/request/ThemeRequest.java | 14 ++-- .../request/ReservationRequestTest.java | 79 ++++++++----------- .../request/ReservationTimeRequestTest.java | 6 +- .../controller/request/ThemeRequestTest.java | 52 ++++++++++++ 6 files changed, 114 insertions(+), 63 deletions(-) create mode 100644 src/test/java/roomescape/controller/request/ThemeRequestTest.java diff --git a/src/main/java/roomescape/controller/request/ReservationRequest.java b/src/main/java/roomescape/controller/request/ReservationRequest.java index 1995c3b253..f38ec3e440 100644 --- a/src/main/java/roomescape/controller/request/ReservationRequest.java +++ b/src/main/java/roomescape/controller/request/ReservationRequest.java @@ -12,23 +12,29 @@ public class ReservationRequest { private final long themeId; public ReservationRequest(String name, LocalDate date, Long timeId, Long themeId) { - validateNull(date, timeId, themeId); - validateName(name); + validate(name, date, timeId, themeId); this.name = name; this.date = date; this.timeId = timeId; this.themeId = themeId; } - private void validateNull(LocalDate date, Long timeId, Long themeId) { - if (date == null || timeId == null || themeId == null) { - throw new BadRequestException("[ERROR] 유효하지 않은 요청입니다."); + private void validate(String name, LocalDate date, Long timeId, Long themeId) { + validateName(name); + validateNull(date); + validateNull(timeId); + validateNull(themeId); + } + + private void validateNull(Object value) { + if (value == null) { + throw new BadRequestException("[ERROR] 요청된 데이터에 null 혹은 비어있는 값이 존재합니다."); } } private void validateName(String name) { - if (name == null || name.isEmpty()) { - throw new BadRequestException("[ERROR] 유효하지 않은 요청입니다."); + if (name == null || name.isBlank()) { + throw new BadRequestException("[ERROR] 요청된 데이터에 null 혹은 비어있는 값이 존재합니다."); } } diff --git a/src/main/java/roomescape/controller/request/ReservationTimeRequest.java b/src/main/java/roomescape/controller/request/ReservationTimeRequest.java index d6e5084c3b..dc9387f662 100644 --- a/src/main/java/roomescape/controller/request/ReservationTimeRequest.java +++ b/src/main/java/roomescape/controller/request/ReservationTimeRequest.java @@ -9,16 +9,16 @@ public class ReservationTimeRequest { private LocalTime startAt; public ReservationTimeRequest(LocalTime startAt) { - validateTime(startAt); + validateNull(startAt); this.startAt = startAt; } private ReservationTimeRequest() { } - private void validateTime(LocalTime startAt) { + private void validateNull(LocalTime startAt) { if (startAt == null) { - throw new BadRequestException("[ERROR] 유효하지 않은 요청입니다."); + throw new BadRequestException("[ERROR] 요청된 데이터에 null 혹은 비어있는 값이 존재합니다."); } } diff --git a/src/main/java/roomescape/controller/request/ThemeRequest.java b/src/main/java/roomescape/controller/request/ThemeRequest.java index d04cf7fcf9..176efc23f5 100644 --- a/src/main/java/roomescape/controller/request/ThemeRequest.java +++ b/src/main/java/roomescape/controller/request/ThemeRequest.java @@ -9,17 +9,21 @@ public class ThemeRequest { private final String thumbnail; public ThemeRequest(String name, String description, String thumbnail) { - validateNull(name); - validateNull(description); - validateNull(thumbnail); + validate(name, description, thumbnail); this.name = name; this.description = description; this.thumbnail = thumbnail; } + private void validate(String name, String description, String thumbnail) { + validateNull(name); + validateNull(description); + validateNull(thumbnail); + } + private void validateNull(String value) { - if (value == null || value.isEmpty()) { - throw new BadRequestException("[ERROR] 유효하지 않은 요청입니다."); + if (value == null || value.isBlank()) { + throw new BadRequestException("[ERROR] 요청된 데이터에 null 혹은 비어있는 값이 존재합니다."); } } diff --git a/src/test/java/roomescape/controller/request/ReservationRequestTest.java b/src/test/java/roomescape/controller/request/ReservationRequestTest.java index fd0feedc5d..a5dd5d6c0c 100644 --- a/src/test/java/roomescape/controller/request/ReservationRequestTest.java +++ b/src/test/java/roomescape/controller/request/ReservationRequestTest.java @@ -4,59 +4,48 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.NullAndEmptySource; +import org.junit.jupiter.params.provider.NullSource; import org.junit.jupiter.params.provider.ValueSource; import roomescape.exception.BadRequestException; +import java.time.LocalDate; + import static org.assertj.core.api.Assertions.assertThatThrownBy; class ReservationRequestTest { - @Nested - class ReservationRequestNameTest { - - @DisplayName("예약자명이 null인 경우 예외를 발생시킨다.") - @Test - void should_throw_exception_when_name_is_null() { - assertThatThrownBy(() -> new ReservationRequest("a", null, 1L, 1L)) - .isInstanceOf(BadRequestException.class) - .hasMessage("[ERROR] 유효하지 않은 요청입니다."); - } - - @DisplayName("예약자명이 빈 문자열인 경우 예외를 발생시킨다.") - @Test - void should_throw_exception_when_name_is_empty() { - assertThatThrownBy(() -> new ReservationRequest("a", null, 1L, 1L)) - .isInstanceOf(BadRequestException.class) - .hasMessage("[ERROR] 유효하지 않은 요청입니다."); - } + @DisplayName("요청된 데이터의 예약자명이 null 혹은 비어있는 경우 예외를 발생시킨다.") + @ParameterizedTest + @NullAndEmptySource + @ValueSource(strings = {" ", "\n", "\t"}) + void should_throw_exception_when_invalid_name(String name) { + assertThatThrownBy(() -> new ReservationRequest(name, LocalDate.now(), 1L, 1L)) + .isInstanceOf(BadRequestException.class) + .hasMessage("[ERROR] 요청된 데이터에 null 혹은 비어있는 값이 존재합니다."); + } + + @DisplayName("요청된 데이터의 날짜가 null인 경우 예외를 발생시킨다.") + @Test + void should_throw_exception_when_invalid_date() { + assertThatThrownBy(() -> new ReservationRequest("n", null, 1L, 1L)) + .isInstanceOf(BadRequestException.class) + .hasMessage("[ERROR] 요청된 데이터에 null 혹은 비어있는 값이 존재합니다."); + } + + @DisplayName("요청된 데이터의 시간 id가 null인 경우 예외를 발생시킨다.") + @Test + void should_throw_exception_when_invalid_timeId() { + assertThatThrownBy(() -> new ReservationRequest("n", LocalDate.now(), null, 1L)) + .isInstanceOf(BadRequestException.class) + .hasMessage("[ERROR] 요청된 데이터에 null 혹은 비어있는 값이 존재합니다."); } - @Nested - class ReservationRequestDateTest { - - @DisplayName("날짜가 null인 경우 예외를 발생시킨다.") - @Test - void should_throw_exception_when_date_is_null() { - assertThatThrownBy(() -> new ReservationRequest("a", null, 1L, 1L)) - .isInstanceOf(BadRequestException.class) - .hasMessage("[ERROR] 유효하지 않은 요청입니다."); - } - - @DisplayName("날짜가 비어있는 경우 예외를 발생시킨다.") - @Test - void should_throw_exception_when_date_is_empty() { - assertThatThrownBy(() -> new ReservationRequest("a", null, 1L, 1L)) - .isInstanceOf(BadRequestException.class) - .hasMessage("[ERROR] 유효하지 않은 요청입니다."); - } - - @DisplayName("날짜의 형식이 유효하지 않은 경우 예외를 발생시킨다.") - @ParameterizedTest - @ValueSource(strings = {"2024:03:27", "2024/01/11", "에베", "12-12"}) - void should_throw_exception_when_date_is_bad_format(String date) { - assertThatThrownBy(() -> new ReservationRequest("a", null, 1L, 1L)) - .isInstanceOf(BadRequestException.class) - .hasMessage("[ERROR] 유효하지 않은 요청입니다."); - } + @DisplayName("요청된 데이터의 테마 id가 null인 경우 예외를 발생시킨다.") + @Test + void should_throw_exception_when_invalid_themeId() { + assertThatThrownBy(() -> new ReservationRequest("n", LocalDate.now(), 1L, null)) + .isInstanceOf(BadRequestException.class) + .hasMessage("[ERROR] 요청된 데이터에 null 혹은 비어있는 값이 존재합니다."); } } diff --git a/src/test/java/roomescape/controller/request/ReservationTimeRequestTest.java b/src/test/java/roomescape/controller/request/ReservationTimeRequestTest.java index 089849c057..24bacded12 100644 --- a/src/test/java/roomescape/controller/request/ReservationTimeRequestTest.java +++ b/src/test/java/roomescape/controller/request/ReservationTimeRequestTest.java @@ -13,15 +13,15 @@ class ReservationTimeRequestTest { - @DisplayName("시간이 null인 경우 예외를 발생시킨다.") + @DisplayName("요청된 시간이 null인 경우 예외를 발생시킨다.") @Test void should_throw_exception_when_startAt_is_null() { assertThatThrownBy(() -> new ReservationTimeRequest(null)) .isInstanceOf(BadRequestException.class) - .hasMessage("[ERROR] 유효하지 않은 요청입니다."); + .hasMessage("[ERROR] 요청된 데이터에 null 혹은 비어있는 값이 존재합니다."); } - @DisplayName("유효한 시간이면 예외가 발생하지 않는다.") + @DisplayName("요청된 시간이 유효한 경우 예외가 발생하지 않는다.") @ParameterizedTest @ValueSource(strings = {"10:00", "23:59:59", "12:00:00", "00:00:00"}) void should_not_throw_exception_when_startAt_is_good_format(String startAt) { diff --git a/src/test/java/roomescape/controller/request/ThemeRequestTest.java b/src/test/java/roomescape/controller/request/ThemeRequestTest.java new file mode 100644 index 0000000000..ef3a75e796 --- /dev/null +++ b/src/test/java/roomescape/controller/request/ThemeRequestTest.java @@ -0,0 +1,52 @@ +package roomescape.controller.request; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.NullAndEmptySource; +import org.junit.jupiter.params.provider.ValueSource; +import roomescape.exception.BadRequestException; + +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class ThemeRequestTest { + + @DisplayName("요청된 데이터의 이름이 null 혹은 비어있는 경우 예외를 발생시킨다.") + @ParameterizedTest + @NullAndEmptySource + @ValueSource(strings = {" ", "\n", "\t"}) + void should_throw_exception_when_invalid_name(String name) { + assertThatThrownBy(() -> new ThemeRequest(name, "d", "t")) + .isInstanceOf(BadRequestException.class) + .hasMessage("[ERROR] 요청된 데이터에 null 혹은 비어있는 값이 존재합니다."); + } + + @DisplayName("요청된 데이터의 설명이 null 혹은 비어있는 경우 예외를 발생시킨다.") + @ParameterizedTest + @NullAndEmptySource + @ValueSource(strings = {" ", "\n", "\t"}) + void should_throw_exception_when_invalid_description(String description) { + assertThatThrownBy(() -> new ThemeRequest("n", description, "t")) + .isInstanceOf(BadRequestException.class) + .hasMessage("[ERROR] 요청된 데이터에 null 혹은 비어있는 값이 존재합니다."); + } + + @DisplayName("요청된 데이터의 썸네일이 null 혹은 비어있는 경우 예외를 발생시킨다.") + @ParameterizedTest + @NullAndEmptySource + @ValueSource(strings = {" ", "\n", "\t"}) + void should_throw_exception_when_invalid_thumbnail(String thumbnail) { + assertThatThrownBy(() -> new ThemeRequest("n", "d", thumbnail)) + .isInstanceOf(BadRequestException.class) + .hasMessage("[ERROR] 요청된 데이터에 null 혹은 비어있는 값이 존재합니다."); + } + + @DisplayName("요청된 데이터가 유효한 경우 예외가 발생하지 않는다.") + @ParameterizedTest + @CsvSource(value = {"nnn,ddd,ttt", "111,222,333", " n , d , t"}) + void should_not_throw_exception_when_valid_data(String name, String description, String thumbnail) { + assertThatCode(() -> new ThemeRequest(name, description, thumbnail)) + .doesNotThrowAnyException(); + } +} From fe8c42d0c27745383686dd7335283333ba154cf6 Mon Sep 17 00:00:00 2001 From: SCY Date: Tue, 7 May 2024 02:52:11 +0900 Subject: [PATCH 69/74] =?UTF-8?q?feat(model):=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EA=B2=80=EC=A6=9D=20=EB=A1=9C=EC=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/roomescape/model/Reservation.java | 49 +++++++++- .../roomescape/model/ReservationTime.java | 38 ++++++-- src/main/java/roomescape/model/Theme.java | 34 ++++++- .../service/ReservationService.java | 3 +- .../service/ReservationTimeService.java | 2 +- .../roomescape/model/ReservationTest.java | 97 +++++++++++++++++++ .../roomescape/model/ReservationTimeTest.java | 51 ++++++++++ src/test/java/roomescape/model/ThemeTest.java | 71 ++++++++++++++ .../repository/ReservationRepositoryTest.java | 10 +- .../ReservationTimeRepositoryTest.java | 4 +- .../repository/ThemeRepositoryTest.java | 4 +- .../dao/ReservationTimeDaoTest.java | 4 +- .../repository/dao/ThemeDaoTest.java | 4 +- 13 files changed, 346 insertions(+), 25 deletions(-) create mode 100644 src/test/java/roomescape/model/ReservationTest.java create mode 100644 src/test/java/roomescape/model/ReservationTimeTest.java create mode 100644 src/test/java/roomescape/model/ThemeTest.java diff --git a/src/main/java/roomescape/model/Reservation.java b/src/main/java/roomescape/model/Reservation.java index fc18962493..eff358fbc5 100644 --- a/src/main/java/roomescape/model/Reservation.java +++ b/src/main/java/roomescape/model/Reservation.java @@ -1,5 +1,7 @@ package roomescape.model; +import roomescape.service.dto.ReservationDto; + import java.time.LocalDate; import java.util.Objects; @@ -11,10 +13,8 @@ public class Reservation { private ReservationTime time; private Theme theme; - private Reservation() { - } - public Reservation(long id, String name, LocalDate date, ReservationTime time, Theme theme) { + validate(id, name, date, time, theme); this.id = id; this.name = name; this.date = date; @@ -22,13 +22,54 @@ public Reservation(long id, String name, LocalDate date, ReservationTime time, T this.theme = theme; } - public Reservation(String name, LocalDate date, ReservationTime time, Theme theme) { + private Reservation(String name, LocalDate date, ReservationTime time, Theme theme) { + validate(name, date, time, theme); + this.id = 0; this.name = name; this.date = date; this.time = time; this.theme = theme; } + private Reservation() { + } + + public static Reservation from(ReservationDto reservationDto, ReservationTime time, Theme theme) { + return new Reservation(reservationDto.getName(), reservationDto.getDate(), time, theme); + } + + private void validate(long id, String name, LocalDate date, ReservationTime time, Theme theme) { + validateRange(id); + validate(name, date, time, theme); + } + + private void validate(String name, LocalDate date, ReservationTime time, Theme theme) { + validateNull(name); + validateEmpty(name); + validateNull(date); + validateNull(time); + validateNull(theme); + } + + + private void validateRange(long id) { + if (id <= 0) { + throw new IllegalStateException("[ERROR] id는 0 이하일 수 없습니다."); + } + } + + private void validateNull(Object value) { + if (value == null) { + throw new IllegalStateException("[ERROR] 데이터는 null 혹은 빈 문자열일 수 없습니다."); + } + } + + private void validateEmpty(String value) { + if (value.isBlank()) { + throw new IllegalStateException("[ERROR] 데이터는 null 혹은 빈 문자열일 수 없습니다."); + } + } + public long getId() { return id; } diff --git a/src/main/java/roomescape/model/ReservationTime.java b/src/main/java/roomescape/model/ReservationTime.java index c174f501ab..de01dcaab8 100644 --- a/src/main/java/roomescape/model/ReservationTime.java +++ b/src/main/java/roomescape/model/ReservationTime.java @@ -1,23 +1,49 @@ package roomescape.model; +import roomescape.service.dto.ReservationTimeDto; + import java.time.LocalTime; import java.util.Objects; public class ReservationTime { - private long id; // Long + private long id; private LocalTime startAt; - private ReservationTime() { + public ReservationTime(long id, LocalTime startAt) { + validate(id, startAt); + this.id = id; + this.startAt = startAt; } - public ReservationTime(LocalTime startAt) { + private ReservationTime(LocalTime startAt) { + validateNull(startAt); + this.id = 0; this.startAt = startAt; } - public ReservationTime(long id, LocalTime startAt) { - this.id = id; - this.startAt = startAt; + private ReservationTime() { + } + + public static ReservationTime from(ReservationTimeDto reservationTimeDto) { + return new ReservationTime(reservationTimeDto.getStartAt()); + } + + private void validate(long id, LocalTime startAt) { + validateRange(id); + validateNull(startAt); + } + + private void validateRange(long id) { + if (id <= 0) { + throw new IllegalStateException("[ERROR] id는 0 이하일 수 없습니다."); + } + } + + private void validateNull(LocalTime value) { + if (value == null) { + throw new IllegalStateException("[ERROR] 데이터는 null 혹은 빈 문자열일 수 없습니다."); + } } public long getId() { diff --git a/src/main/java/roomescape/model/Theme.java b/src/main/java/roomescape/model/Theme.java index 47e63c19bc..b9b8ccbdef 100644 --- a/src/main/java/roomescape/model/Theme.java +++ b/src/main/java/roomescape/model/Theme.java @@ -11,26 +11,52 @@ public class Theme { private String description; private String thumbnail; - private Theme() { - } - public Theme(long id, String name, String description, String thumbnail) { + validate(id, name, description, thumbnail); this.id = id; this.name = name; this.description = description; this.thumbnail = thumbnail; } - public Theme(String name, String description, String thumbnail) { + private Theme(String name, String description, String thumbnail) { + validate(name, description, thumbnail); + this.id = 0; this.name = name; this.description = description; this.thumbnail = thumbnail; } + private Theme() { + } + public static Theme from(ThemeDto themeDto) { return new Theme(themeDto.getName(), themeDto.getDescription(), themeDto.getThumbnail()); } + private void validate(long id, String name, String description, String thumbnail) { + validateRange(id); + validate(name, description, thumbnail); + } + + private void validate(String name, String description, String thumbnail) { + validateNull(name); + validateNull(description); + validateNull(thumbnail); + } + + private void validateRange(long id) { + if (id <= 0) { + throw new IllegalStateException("[ERROR] id는 0 이하일 수 없습니다."); + } + } + + private void validateNull(String value) { + if (value == null || value.isBlank()) { + throw new IllegalStateException("[ERROR] 데이터는 null 혹은 빈 문자열일 수 없습니다."); + } + } + public long getId() { return id; } diff --git a/src/main/java/roomescape/service/ReservationService.java b/src/main/java/roomescape/service/ReservationService.java index e608f9d0e9..f709761d94 100644 --- a/src/main/java/roomescape/service/ReservationService.java +++ b/src/main/java/roomescape/service/ReservationService.java @@ -32,7 +32,6 @@ public List findAllReservations() { } public Reservation saveReservation(ReservationDto reservationDto) { - String name = reservationDto.getName(); LocalDate date = reservationDto.getDate(); long timeId = reservationDto.getTimeId(); long themeId = reservationDto.getThemeId(); @@ -42,7 +41,7 @@ public Reservation saveReservation(ReservationDto reservationDto) { .orElseThrow(() -> new BadRequestException("[ERROR] 데이터가 저장되지 않습니다.")); validate(date, time); - Reservation reservation = new Reservation(name, date, time, theme); + Reservation reservation = Reservation.from(reservationDto, time, theme); return reservationRepository.saveReservation(reservation); } diff --git a/src/main/java/roomescape/service/ReservationTimeService.java b/src/main/java/roomescape/service/ReservationTimeService.java index 0b829d8e30..b67dda406c 100644 --- a/src/main/java/roomescape/service/ReservationTimeService.java +++ b/src/main/java/roomescape/service/ReservationTimeService.java @@ -27,7 +27,7 @@ public List findAllReservationTimes() { public ReservationTime saveReservationTime(ReservationTimeDto reservationTimeDto) { LocalTime startAt = reservationTimeDto.getStartAt(); validateDuplication(startAt); - ReservationTime reservationTime = new ReservationTime(reservationTimeDto.getStartAt()); + ReservationTime reservationTime = ReservationTime.from(reservationTimeDto); return reservationTimeRepository.saveReservationTime(reservationTime) .orElseThrow(() -> new BadRequestException("[ERROR] 데이터가 저장되지 않습니다.")); } diff --git a/src/test/java/roomescape/model/ReservationTest.java b/src/test/java/roomescape/model/ReservationTest.java new file mode 100644 index 0000000000..4fe9cd8758 --- /dev/null +++ b/src/test/java/roomescape/model/ReservationTest.java @@ -0,0 +1,97 @@ +package roomescape.model; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.NullAndEmptySource; +import org.junit.jupiter.params.provider.NullSource; +import org.junit.jupiter.params.provider.ValueSource; +import roomescape.controller.request.ReservationRequest; +import roomescape.exception.BadRequestException; +import roomescape.service.dto.ReservationDto; + +import java.time.LocalDate; +import java.time.LocalTime; + +import static org.assertj.core.api.Assertions.*; + +public class ReservationTest { + + @DisplayName("데이터의 id가 0 이하인 경우 예외를 발생시킨다.") + @ParameterizedTest + @ValueSource(longs = {0, -1, -999}) + void should_throw_exception_when_invalid_id(long id) { + ReservationTime reservationTime = new ReservationTime(1L, LocalTime.now()); + Theme theme = new Theme(1L, "n", "d", "t"); + assertThatThrownBy(() -> new Reservation(id, "n", LocalDate.now(), reservationTime, theme)) + .isInstanceOf(IllegalStateException.class) + .hasMessage("[ERROR] id는 0 이하일 수 없습니다."); + } + + @DisplayName("데이터의 이름이 null 혹은 비어있는 경우 예외를 발생시킨다.") + @ParameterizedTest + @NullAndEmptySource + @ValueSource(strings = {" ", "\n", "\t"}) + void should_throw_exception_when_invalid_name(String name) { + ReservationTime reservationTime = new ReservationTime(1L, LocalTime.now()); + Theme theme = new Theme(1L, "n", "d", "t"); + assertThatThrownBy(() -> new Reservation(1L, name, LocalDate.now(), reservationTime, theme)) + .isInstanceOf(IllegalStateException.class) + .hasMessage("[ERROR] 데이터는 null 혹은 빈 문자열일 수 없습니다."); + } + + @DisplayName("데이터의 날짜가 null인 경우 예외를 발생시킨다.") + @Test + void should_throw_exception_when_invalid_date() { + ReservationTime reservationTime = new ReservationTime(1L, LocalTime.now()); + Theme theme = new Theme(1L, "n", "d", "t"); + assertThatThrownBy(() -> new Reservation(1L, "n", null, reservationTime, theme)) + .isInstanceOf(IllegalStateException.class) + .hasMessage("[ERROR] 데이터는 null 혹은 빈 문자열일 수 없습니다."); + } + + @DisplayName("데이터의 시간이 null인 경우 예외를 발생시킨다.") + @Test + void should_throw_exception_when_invalid_time() { + ReservationTime reservationTime = null; + Theme theme = new Theme(1L, "n", "d", "t"); + assertThatThrownBy(() -> new Reservation(1L, "n", LocalDate.now(), reservationTime, theme)) + .isInstanceOf(IllegalStateException.class) + .hasMessage("[ERROR] 데이터는 null 혹은 빈 문자열일 수 없습니다."); + } + + @DisplayName("데이터의 테마가 null인 경우 예외를 발생시킨다.") + @Test + void should_throw_exception_when_invalid_theme() { + ReservationTime reservationTime = new ReservationTime(1L, LocalTime.now()); + Theme theme = null; + assertThatThrownBy(() -> new Reservation(1L, "n", LocalDate.now(), reservationTime, theme)) + .isInstanceOf(IllegalStateException.class) + .hasMessage("[ERROR] 데이터는 null 혹은 빈 문자열일 수 없습니다."); + } + + @DisplayName("데이터가 유효한 경우 예외가 발생하지 않는다.") + @ParameterizedTest + @CsvSource(value = {"1,nnn,2024-05-07,02:00,ddd,ttt", " 1 ,n nn,2024-05-07,02:00, dd d, t!tt "}) + void should_not_throw_exception_when_valid_data(long id, String name, String rawDate, String rawTime, String description, String thumbnail) { + LocalDate date = LocalDate.parse(rawDate); + LocalTime time = LocalTime.parse(rawTime); + ReservationTime reservationTime = new ReservationTime(1L, time); + Theme theme = new Theme(1L, name, description, thumbnail); + assertThatCode(() -> new Reservation(id, name, date, reservationTime, theme)) + .doesNotThrowAnyException(); + } + + @DisplayName("DTO를 도메인으로 변환하는 경우 id는 0이 될 수 있다.") + @Test + void should_be_zero_id_when_convert_dto() { + ReservationTime time = new ReservationTime(1L, LocalTime.now()); + Theme theme = new Theme(1L, "n", "d", "t"); + ReservationDto ReservationDto = new ReservationDto("n", LocalDate.now(), 1L, 1L); + assertThatCode(() -> { + Reservation reservation = Reservation.from(ReservationDto, time, theme); + assertThat(reservation.getId()).isEqualTo(0); + }).doesNotThrowAnyException(); + } +} diff --git a/src/test/java/roomescape/model/ReservationTimeTest.java b/src/test/java/roomescape/model/ReservationTimeTest.java new file mode 100644 index 0000000000..5bcc4646d7 --- /dev/null +++ b/src/test/java/roomescape/model/ReservationTimeTest.java @@ -0,0 +1,51 @@ +package roomescape.model; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.ValueSource; +import roomescape.service.dto.ReservationTimeDto; + +import java.time.LocalTime; + +import static org.assertj.core.api.Assertions.*; + +public class ReservationTimeTest { + + @DisplayName("데이터의 id가 0 이하인 경우 예외를 발생시킨다.") + @ParameterizedTest + @ValueSource(longs = {0, -1, -999}) + void should_throw_exception_when_invalid_id(long id) { + assertThatThrownBy(() -> new ReservationTime(id, LocalTime.now())) + .isInstanceOf(IllegalStateException.class) + .hasMessage("[ERROR] id는 0 이하일 수 없습니다."); + } + + @DisplayName("데이터의 시간이 null인 경우 예외를 발생시킨다.") + @Test + void should_throw_exception_when_invalid_time() { + assertThatThrownBy(() -> new ReservationTime(1L, null)) + .isInstanceOf(IllegalStateException.class) + .hasMessage("[ERROR] 데이터는 null 혹은 빈 문자열일 수 없습니다."); + } + + @DisplayName("데이터가 유효한 경우 예외가 발생하지 않는다.") + @ParameterizedTest + @CsvSource(value = {"1,01:00", "2,23:59"}) + void should_not_throw_exception_when_valid_data(long id, String rawStartAt) { + LocalTime startAt = LocalTime.parse(rawStartAt); + assertThatCode(() -> new ReservationTime(id, startAt)) + .doesNotThrowAnyException(); + } + + @DisplayName("DTO를 도메인으로 변환하는 경우 id는 0이 될 수 있다.") + @Test + void should_be_zero_id_when_convert_dto() { + ReservationTimeDto reservationTimeDto = new ReservationTimeDto(LocalTime.now()); + assertThatCode(() -> { + ReservationTime time = ReservationTime.from(reservationTimeDto); + assertThat(time.getId()).isEqualTo(0); + }).doesNotThrowAnyException(); + } +} diff --git a/src/test/java/roomescape/model/ThemeTest.java b/src/test/java/roomescape/model/ThemeTest.java new file mode 100644 index 0000000000..0ff4070c81 --- /dev/null +++ b/src/test/java/roomescape/model/ThemeTest.java @@ -0,0 +1,71 @@ +package roomescape.model; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.NullAndEmptySource; +import org.junit.jupiter.params.provider.ValueSource; +import roomescape.service.dto.ThemeDto; + +import static org.assertj.core.api.Assertions.*; + +class ThemeTest { + + @DisplayName("데이터의 id가 0 이하인 경우 예외를 발생시킨다.") + @ParameterizedTest + @ValueSource(longs = {0, -1, -999}) + void should_throw_exception_when_invalid_id(long id) { + assertThatThrownBy(() -> new Theme(id, "n", "d", "t")) + .isInstanceOf(IllegalStateException.class) + .hasMessage("[ERROR] id는 0 이하일 수 없습니다."); + } + + @DisplayName("데이터의 이름이 null 혹은 비어있는 경우 예외를 발생시킨다.") + @ParameterizedTest + @NullAndEmptySource + @ValueSource(strings = {" ", "\n", "\t"}) + void should_throw_exception_when_invalid_name(String name) { + assertThatThrownBy(() -> new Theme(1L, name, "d", "t")) + .isInstanceOf(IllegalStateException.class) + .hasMessage("[ERROR] 데이터는 null 혹은 빈 문자열일 수 없습니다."); + } + + @DisplayName("데이터의 설명이 null 혹은 비어있는 경우 예외를 발생시킨다.") + @ParameterizedTest + @NullAndEmptySource + @ValueSource(strings = {" ", "\n", "\t"}) + void should_throw_exception_when_invalid_description(String description) { + assertThatThrownBy(() -> new Theme(1L, "n", description, "t")) + .isInstanceOf(IllegalStateException.class) + .hasMessage("[ERROR] 데이터는 null 혹은 빈 문자열일 수 없습니다."); + } + + @DisplayName("데이터의 썸네일이 null 혹은 비어있는 경우 예외를 발생시킨다.") + @ParameterizedTest + @NullAndEmptySource + @ValueSource(strings = {" ", "\n", "\t"}) + void should_throw_exception_when_invalid_thumbnail(String thumbnail) { + assertThatThrownBy(() -> new Theme(1L, "n", "d", thumbnail)) + .isInstanceOf(IllegalStateException.class) + .hasMessage("[ERROR] 데이터는 null 혹은 빈 문자열일 수 없습니다."); + } + + @DisplayName("데이터가 유효한 경우 예외가 발생하지 않는다.") + @ParameterizedTest + @CsvSource(value = {"1,nnn,ddd,ttt", "1,111,222,333", "1, n , d , t"}) + void should_not_throw_exception_when_valid_data(long id, String name, String description, String thumbnail) { + assertThatCode(() -> new Theme(id, name, description, thumbnail)) + .doesNotThrowAnyException(); + } + + @DisplayName("DTO를 도메인으로 변환하는 경우 id는 0이 될 수 있다.") + @Test + void should_be_zero_id_when_convert_dto() { + ThemeDto themeDto = new ThemeDto("n", "d", "t"); + assertThatCode(() -> { + Theme theme = Theme.from(themeDto); + assertThat(theme.getId()).isEqualTo(0); + }).doesNotThrowAnyException(); + } +} diff --git a/src/test/java/roomescape/repository/ReservationRepositoryTest.java b/src/test/java/roomescape/repository/ReservationRepositoryTest.java index 905303863c..68fdf0ef54 100644 --- a/src/test/java/roomescape/repository/ReservationRepositoryTest.java +++ b/src/test/java/roomescape/repository/ReservationRepositoryTest.java @@ -11,6 +11,7 @@ import roomescape.model.Reservation; import roomescape.model.ReservationTime; import roomescape.model.Theme; +import roomescape.service.dto.ReservationDto; import java.time.LocalDate; import java.time.LocalTime; @@ -127,12 +128,13 @@ void should_return_false_when_not_exist_reservation_by_date_and_timeId() { @DisplayName("예약을 저장한 후 저장된 예약을 반환한다.") @Test void should_save_reservation() { - ReservationTime time = new ReservationTime(1, LocalTime.of(1, 0)); - Theme theme = new Theme(1, "n1", "d1", "t1"); - Reservation before = new Reservation("n3", LocalDate.of(2000, 1, 3), time, theme); + ReservationDto reservationDto = new ReservationDto("n3", LocalDate.of(2000, 1, 3), 1L, 1L); + ReservationTime time = new ReservationTime(1L, LocalTime.of(1, 0)); + Theme theme = new Theme(1L, "n1", "d1", "t1"); + Reservation before = Reservation.from(reservationDto, time, theme); Reservation actual = reservationRepository.saveReservation(before); - Reservation after = new Reservation(3, "n3", LocalDate.of(2000, 1, 3), time, theme); + Reservation after = new Reservation(3L, "n3", LocalDate.of(2000, 1, 3), time, theme); assertThat(actual).isEqualTo(after); } diff --git a/src/test/java/roomescape/repository/ReservationTimeRepositoryTest.java b/src/test/java/roomescape/repository/ReservationTimeRepositoryTest.java index aa1bc914fa..ad611d680a 100644 --- a/src/test/java/roomescape/repository/ReservationTimeRepositoryTest.java +++ b/src/test/java/roomescape/repository/ReservationTimeRepositoryTest.java @@ -9,6 +9,7 @@ import org.springframework.jdbc.core.simple.SimpleJdbcInsert; import org.springframework.test.annotation.DirtiesContext; import roomescape.model.ReservationTime; +import roomescape.service.dto.ReservationTimeDto; import java.time.LocalTime; import java.util.HashMap; @@ -107,7 +108,8 @@ void should_find_reservation_time_by_id() { @DisplayName("예약 시간을 저장한 후 저장된 시간을 반환한다.") @Test void should_save_reservation_time() { - ReservationTime before = new ReservationTime(LocalTime.of(3, 0)); + ReservationTimeDto reservationTimeDto = new ReservationTimeDto(LocalTime.of(3, 0)); + ReservationTime before = ReservationTime.from(reservationTimeDto); Optional actual = reservationTimeRepository.saveReservationTime(before); diff --git a/src/test/java/roomescape/repository/ThemeRepositoryTest.java b/src/test/java/roomescape/repository/ThemeRepositoryTest.java index 3b0e603171..aeac34b4b0 100644 --- a/src/test/java/roomescape/repository/ThemeRepositoryTest.java +++ b/src/test/java/roomescape/repository/ThemeRepositoryTest.java @@ -9,6 +9,7 @@ import org.springframework.jdbc.core.simple.SimpleJdbcInsert; import org.springframework.test.annotation.DirtiesContext; import roomescape.model.Theme; +import roomescape.service.dto.ThemeDto; import java.time.LocalDate; import java.util.HashMap; @@ -96,7 +97,8 @@ void should_find_all_themes() { @DisplayName("테마를 저장한 후 저장된 테마를 반환한다.") @Test void should_save_theme_and_return() { - Theme before = new Theme("n3", "d3", "t3"); + ThemeDto themeDto = new ThemeDto("n3", "d3", "t3"); + Theme before = Theme.from(themeDto); Optional actual = themeRepository.saveTheme(before); diff --git a/src/test/java/roomescape/repository/dao/ReservationTimeDaoTest.java b/src/test/java/roomescape/repository/dao/ReservationTimeDaoTest.java index aaf617a287..ae6e5512f0 100644 --- a/src/test/java/roomescape/repository/dao/ReservationTimeDaoTest.java +++ b/src/test/java/roomescape/repository/dao/ReservationTimeDaoTest.java @@ -9,6 +9,7 @@ import org.springframework.jdbc.core.simple.SimpleJdbcInsert; import org.springframework.test.annotation.DirtiesContext; import roomescape.model.ReservationTime; +import roomescape.service.dto.ReservationTimeDto; import java.time.LocalTime; import java.util.HashMap; @@ -58,7 +59,8 @@ private void insertReservationTime(String startAt) { @DisplayName("예약 시간을 저장한다.") @Test void should_save_reservation_time() { - ReservationTime time = new ReservationTime(LocalTime.of(3, 0)); + ReservationTimeDto reservationTimeDto = new ReservationTimeDto(LocalTime.of(3, 0)); + ReservationTime time = ReservationTime.from(reservationTimeDto); reservationTimeDao.save(time); assertThat(reservationTimeDao.findAll()).hasSize(INITIAL_TIME_COUNT + 1); } diff --git a/src/test/java/roomescape/repository/dao/ThemeDaoTest.java b/src/test/java/roomescape/repository/dao/ThemeDaoTest.java index 00b57b8c3b..d533288ab8 100644 --- a/src/test/java/roomescape/repository/dao/ThemeDaoTest.java +++ b/src/test/java/roomescape/repository/dao/ThemeDaoTest.java @@ -9,6 +9,7 @@ import org.springframework.jdbc.core.simple.SimpleJdbcInsert; import org.springframework.test.annotation.DirtiesContext; import roomescape.model.Theme; +import roomescape.service.dto.ThemeDto; import java.util.HashMap; import java.util.List; @@ -59,7 +60,8 @@ private void insertTheme(String name, String description, String thumbnail) { @DisplayName("테마를 저장한다.") @Test void should_save_theme() { - Theme theme = new Theme("n3", "d3", "t3"); + ThemeDto themeDto = new ThemeDto("n3", "d3", "t3"); + Theme theme = Theme.from(themeDto); themeDao.save(theme); assertThat(themeDao.findAll()).hasSize(INITIAL_THEME_COUNT + 1); } From ea5184ac78333dab8eec95fc5f5926cdd47c8812 Mon Sep 17 00:00:00 2001 From: SCY Date: Tue, 7 May 2024 02:56:52 +0900 Subject: [PATCH 70/74] =?UTF-8?q?refactor(controller):=20=EC=9A=94?= =?UTF-8?q?=EC=B2=AD=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EA=B2=80=EC=A6=9D=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=BB=A8=ED=8A=B8=EB=A1=A4=EB=9F=AC?= =?UTF-8?q?=EB=A1=9C=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../roomescape/controller/ReservationController.java | 9 +++++++++ .../controller/ReservationTimeController.java | 8 ++++++++ .../java/roomescape/controller/ThemeController.java | 8 ++++++++ .../java/roomescape/service/ReservationService.java | 12 ++---------- .../roomescape/service/ReservationTimeService.java | 9 +-------- src/main/java/roomescape/service/ThemeService.java | 5 +---- 6 files changed, 29 insertions(+), 22 deletions(-) diff --git a/src/main/java/roomescape/controller/ReservationController.java b/src/main/java/roomescape/controller/ReservationController.java index 38f112b227..ad010afe3e 100644 --- a/src/main/java/roomescape/controller/ReservationController.java +++ b/src/main/java/roomescape/controller/ReservationController.java @@ -5,6 +5,7 @@ import roomescape.controller.request.ReservationRequest; import roomescape.controller.response.MemberReservationTimeResponse; import roomescape.controller.response.ReservationResponse; +import roomescape.exception.BadRequestException; import roomescape.model.Reservation; import roomescape.service.ReservationService; import roomescape.service.dto.ReservationDto; @@ -44,6 +45,7 @@ public ResponseEntity addReservation(@RequestBody Reservati @DeleteMapping("/{id}") public ResponseEntity deleteReservation(@PathVariable("id") Long id) { + validateNull(id); reservationService.deleteReservation(id); return ResponseEntity.noContent().build(); } @@ -52,8 +54,15 @@ public ResponseEntity deleteReservation(@PathVariable("id") Long id) { public ResponseEntity> showReservationTimesInformation( @RequestParam(name = "date") LocalDate date, @RequestParam(name = "themeId") Long themeId) { + validateNull(themeId); List response = reservationService.findReservationTimesInformation(date, themeId); // TODO: 여기서 response 객체로 반환하도록 수정 return ResponseEntity.ok(response); } + + private void validateNull(Long value) { + if (value == null) { + throw new BadRequestException("[ERROR] 요청된 데이터에 null 혹은 비어있는 값이 존재합니다."); + } + } } diff --git a/src/main/java/roomescape/controller/ReservationTimeController.java b/src/main/java/roomescape/controller/ReservationTimeController.java index c4b3334176..1f25e9eb5c 100644 --- a/src/main/java/roomescape/controller/ReservationTimeController.java +++ b/src/main/java/roomescape/controller/ReservationTimeController.java @@ -4,6 +4,7 @@ import org.springframework.web.bind.annotation.*; import roomescape.controller.request.ReservationTimeRequest; import roomescape.controller.response.ReservationTimeResponse; +import roomescape.exception.BadRequestException; import roomescape.model.ReservationTime; import roomescape.service.ReservationTimeService; import roomescape.service.dto.ReservationTimeDto; @@ -42,7 +43,14 @@ public ResponseEntity addReservationTime(@RequestBody R @DeleteMapping("/{id}") public ResponseEntity deleteReservationTime(@PathVariable("id") Long id) { + validateNull(id); reservationTimeService.deleteReservationTime(id); return ResponseEntity.noContent().build(); } + + private void validateNull(Long value) { + if (value == null) { + throw new BadRequestException("[ERROR] 요청된 데이터에 null 혹은 비어있는 값이 존재합니다."); + } + } } diff --git a/src/main/java/roomescape/controller/ThemeController.java b/src/main/java/roomescape/controller/ThemeController.java index 847955d1bb..6d9e7c735b 100644 --- a/src/main/java/roomescape/controller/ThemeController.java +++ b/src/main/java/roomescape/controller/ThemeController.java @@ -4,6 +4,7 @@ import org.springframework.web.bind.annotation.*; import roomescape.controller.request.ThemeRequest; import roomescape.controller.response.ThemeResponse; +import roomescape.exception.BadRequestException; import roomescape.model.Theme; import roomescape.service.ThemeService; import roomescape.service.dto.ThemeDto; @@ -42,6 +43,7 @@ public ResponseEntity addTheme(@RequestBody ThemeRequest request) @DeleteMapping("/{id}") public ResponseEntity deleteTheme(@PathVariable("id") Long id) { + validateNull(id); themeService.deleteTheme(id); return ResponseEntity.noContent().build(); } @@ -54,4 +56,10 @@ public ResponseEntity> showPopularThemes() { .toList(); return ResponseEntity.ok(response); } + + private void validateNull(Long value) { + if (value == null) { + throw new BadRequestException("[ERROR] 요청된 데이터에 null 혹은 비어있는 값이 존재합니다."); + } + } } diff --git a/src/main/java/roomescape/service/ReservationService.java b/src/main/java/roomescape/service/ReservationService.java index f709761d94..9b018ab5e0 100644 --- a/src/main/java/roomescape/service/ReservationService.java +++ b/src/main/java/roomescape/service/ReservationService.java @@ -65,18 +65,11 @@ private void validateDuplication(LocalDate date, long timeId) { } } - public void deleteReservation(Long id) { - validateNull(id); + public void deleteReservation(long id) { validateExistence(id); reservationRepository.deleteReservationById(id); } - private void validateNull(Long id) { - if (id == null) { - throw new BadRequestException("[ERROR] id에 null이 입력될 수 없습니다."); - } - } - private void validateExistence(long id) { boolean isNotExist = !reservationRepository.isExistReservationById(id); if (isNotExist) { @@ -84,9 +77,8 @@ private void validateExistence(long id) { } } - public List findReservationTimesInformation(LocalDate date, Long themeId) { + public List findReservationTimesInformation(LocalDate date, long themeId) { // TODO: themeId <= 0 예외 처리 - validateNull(themeId); List bookedTimes = reservationRepository.findReservationTimeBooked(date, themeId); List notBookedTimes = reservationRepository.findReservationTimeNotBooked(date, themeId); List bookedResponse = mapToResponse(bookedTimes, true); diff --git a/src/main/java/roomescape/service/ReservationTimeService.java b/src/main/java/roomescape/service/ReservationTimeService.java index b67dda406c..89c9c5a927 100644 --- a/src/main/java/roomescape/service/ReservationTimeService.java +++ b/src/main/java/roomescape/service/ReservationTimeService.java @@ -44,23 +44,16 @@ public ReservationTime findReservationTime(long id) { .orElseThrow(() -> new BadRequestException("[ERROR] 데이터가 저장되지 않습니다.")); } - public void deleteReservationTime(Long id) { + public void deleteReservationTime(long id) { validate(id); reservationTimeRepository.deleteReservationTimeById(id); } private void validate(Long id) { - validateNull(id); validateExistence(id); validateDependence(id); } - private void validateNull(Long id) { - if (id == null) { - throw new BadRequestException("[ERROR] id에 null이 입력될 수 없습니다."); - } - } - private void validateDependence(Long id) { boolean isExist = reservationTimeRepository.isExistReservationByTimeId(id); if (isExist) { diff --git a/src/main/java/roomescape/service/ThemeService.java b/src/main/java/roomescape/service/ThemeService.java index 4a09a205a1..8bffd55f65 100644 --- a/src/main/java/roomescape/service/ThemeService.java +++ b/src/main/java/roomescape/service/ThemeService.java @@ -31,10 +31,7 @@ public Theme saveTheme(ThemeDto themeDto) { .orElseThrow(() -> new BadRequestException("[ERROR] 데이터가 저장되지 않습니다.")); } - public void deleteTheme(Long id) { - if (id == null) { - throw new BadRequestException("[ERROR] id에 null이 입력될 수 없습니다."); - } + public void deleteTheme(long id) { themeRepository.deleteThemeById(id); } From e22af938e234b8e45f0fb0fccc7b4abe6dfa54db Mon Sep 17 00:00:00 2001 From: SCY Date: Tue, 7 May 2024 03:34:02 +0900 Subject: [PATCH 71/74] =?UTF-8?q?feat(service):=20=EC=84=9C=EB=B9=84?= =?UTF-8?q?=EC=8A=A4=20=EA=B3=84=EC=B8=B5=20=EA=B2=80=EC=A6=9D=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/ThemeRepository.java | 8 +++ .../repository/dao/JdbcThemeDao.java | 12 ++++ .../roomescape/repository/dao/ThemeDao.java | 4 ++ .../service/ReservationService.java | 67 ++++++++++--------- .../service/ReservationTimeService.java | 43 ++++++------ .../java/roomescape/service/ThemeService.java | 23 ++++++- .../request/ReservationRequestTest.java | 2 - .../roomescape/model/ReservationTest.java | 3 - .../service/ReservationServiceTest.java | 44 ++++++------ .../service/ReservationTimeServiceTest.java | 21 +++++- .../roomescape/service/ThemeServiceTest.java | 20 ++++++ .../service/fakedao/FakeThemeDao.java | 10 +++ 12 files changed, 173 insertions(+), 84 deletions(-) diff --git a/src/main/java/roomescape/repository/ThemeRepository.java b/src/main/java/roomescape/repository/ThemeRepository.java index 89df8ba5f0..bb8a4e15fb 100644 --- a/src/main/java/roomescape/repository/ThemeRepository.java +++ b/src/main/java/roomescape/repository/ThemeRepository.java @@ -44,4 +44,12 @@ public List findThemeRankingByDate(LocalDate startDate, LocalDate endDate } return result; } + + public boolean isExistThemeById(long id) { + return themeDao.isExistById(id); + } + + public boolean isExistThemeByName(String name) { + return themeDao.isExistByName(name); + } } diff --git a/src/main/java/roomescape/repository/dao/JdbcThemeDao.java b/src/main/java/roomescape/repository/dao/JdbcThemeDao.java index da8a368073..45057f6aec 100644 --- a/src/main/java/roomescape/repository/dao/JdbcThemeDao.java +++ b/src/main/java/roomescape/repository/dao/JdbcThemeDao.java @@ -62,4 +62,16 @@ public void deleteById(long id) { String sql = "delete from theme where id = ?"; jdbcTemplate.update(sql, id); } + + @Override + public Boolean isExistById(long id) { + String sql = "select exists(select id from theme where id = ?)"; + return jdbcTemplate.queryForObject(sql, Boolean.class, id); + } + + @Override + public Boolean isExistByName(String name) { + String sql = "select exists (select id from theme where name = ?)"; + return jdbcTemplate.queryForObject(sql, Boolean.class, name); + } } diff --git a/src/main/java/roomescape/repository/dao/ThemeDao.java b/src/main/java/roomescape/repository/dao/ThemeDao.java index a99fa8c096..3797464320 100644 --- a/src/main/java/roomescape/repository/dao/ThemeDao.java +++ b/src/main/java/roomescape/repository/dao/ThemeDao.java @@ -14,4 +14,8 @@ public interface ThemeDao { Optional findById(long id); void deleteById(long id); + + Boolean isExistById(long id); + + Boolean isExistByName(String name); } diff --git a/src/main/java/roomescape/service/ReservationService.java b/src/main/java/roomescape/service/ReservationService.java index 9b018ab5e0..7b51f9777a 100644 --- a/src/main/java/roomescape/service/ReservationService.java +++ b/src/main/java/roomescape/service/ReservationService.java @@ -16,6 +16,7 @@ import java.time.LocalTime; import java.time.temporal.ChronoUnit; import java.util.List; +import java.util.Optional; import java.util.stream.Stream; @Service @@ -32,37 +33,27 @@ public List findAllReservations() { } public Reservation saveReservation(ReservationDto reservationDto) { + ReservationTime time = findReservationTime(reservationDto); + Theme theme = findTheme(reservationDto); + LocalDate date = reservationDto.getDate(); - long timeId = reservationDto.getTimeId(); - long themeId = reservationDto.getThemeId(); - ReservationTime time = reservationRepository.findReservationTimeById(timeId) - .orElseThrow(() -> new BadRequestException("[ERROR] 데이터가 저장되지 않습니다.")); - Theme theme = reservationRepository.findThemeById(themeId) - .orElseThrow(() -> new BadRequestException("[ERROR] 데이터가 저장되지 않습니다.")); + validateIsFuture(date, time.getStartAt()); + validateDuplication(date, time.getId()); - validate(date, time); Reservation reservation = Reservation.from(reservationDto, time, theme); return reservationRepository.saveReservation(reservation); } - private void validate(LocalDate date, ReservationTime time) { - validateDateTime(date, time.getStartAt()); - validateDuplication(date, time.getId()); - } - - private void validateDateTime(LocalDate date, LocalTime time) { - LocalDateTime now = LocalDateTime.now().truncatedTo(ChronoUnit.SECONDS); - LocalDateTime dateTime = LocalDateTime.of(date, time).truncatedTo(ChronoUnit.SECONDS); - if (dateTime.isBefore(now)) { - throw new BadRequestException("[ERROR] 현재 이전 예약은 할 수 없습니다."); - } + private ReservationTime findReservationTime(ReservationDto reservationDto) { + long timeId = reservationDto.getTimeId(); + Optional time = reservationRepository.findReservationTimeById(timeId); + return time.orElseThrow(() -> new BadRequestException("[ERROR] 존재하지 않는 데이터입니다.")); } - private void validateDuplication(LocalDate date, long timeId) { - boolean isExist = reservationRepository.isExistReservationByDateAndTimeId(date, timeId); - if (isExist) { - throw new DuplicatedException("[ERROR] 중복되는 예약은 추가할 수 없습니다."); - } + private Theme findTheme(ReservationDto reservationDto) { + long themeId = reservationDto.getThemeId(); + Optional theme = reservationRepository.findThemeById(themeId); + return theme.orElseThrow(() -> new BadRequestException("[ERROR] 존재하지 않는 데이터입니다.")); } public void deleteReservation(long id) { @@ -70,17 +61,11 @@ public void deleteReservation(long id) { reservationRepository.deleteReservationById(id); } - private void validateExistence(long id) { - boolean isNotExist = !reservationRepository.isExistReservationById(id); - if (isNotExist) { - throw new NotFoundException("[ERROR] 존재하지 않는 예약입니다."); - } - } - public List findReservationTimesInformation(LocalDate date, long themeId) { // TODO: themeId <= 0 예외 처리 List bookedTimes = reservationRepository.findReservationTimeBooked(date, themeId); List notBookedTimes = reservationRepository.findReservationTimeNotBooked(date, themeId); + // TODO: map to response 로직 컨트롤러로 List bookedResponse = mapToResponse(bookedTimes, true); List notBookedResponse = mapToResponse(notBookedTimes, false); return concat(bookedResponse, notBookedResponse); @@ -96,4 +81,26 @@ private List concat(List second) { return Stream.concat(first.stream(), second.stream()).toList(); } + + private void validateIsFuture(LocalDate date, LocalTime time) { + LocalDateTime timeToBook = LocalDateTime.of(date, time).truncatedTo(ChronoUnit.SECONDS); + LocalDateTime now = LocalDateTime.now().truncatedTo(ChronoUnit.SECONDS); + if (timeToBook.isBefore(now)) { + throw new BadRequestException("[ERROR] 현재 이전 예약은 할 수 없습니다."); + } + } + + private void validateDuplication(LocalDate date, long timeId) { + boolean isExist = reservationRepository.isExistReservationByDateAndTimeId(date, timeId); + if (isExist) { + throw new DuplicatedException("[ERROR] 중복되는 예약은 추가할 수 없습니다."); + } + } + + private void validateExistence(long id) { + boolean isNotExist = !reservationRepository.isExistReservationById(id); + if (isNotExist) { + throw new NotFoundException("[ERROR] 존재하지 않는 예약입니다."); + } + } } diff --git a/src/main/java/roomescape/service/ReservationTimeService.java b/src/main/java/roomescape/service/ReservationTimeService.java index 89c9c5a927..e44942cbd3 100644 --- a/src/main/java/roomescape/service/ReservationTimeService.java +++ b/src/main/java/roomescape/service/ReservationTimeService.java @@ -10,6 +10,7 @@ import java.time.LocalTime; import java.util.List; +import java.util.Optional; @Service public class ReservationTimeService { @@ -24,40 +25,29 @@ public List findAllReservationTimes() { return reservationTimeRepository.findAllReservationTimes(); } - public ReservationTime saveReservationTime(ReservationTimeDto reservationTimeDto) { - LocalTime startAt = reservationTimeDto.getStartAt(); - validateDuplication(startAt); - ReservationTime reservationTime = ReservationTime.from(reservationTimeDto); - return reservationTimeRepository.saveReservationTime(reservationTime) - .orElseThrow(() -> new BadRequestException("[ERROR] 데이터가 저장되지 않습니다.")); - } - - private void validateDuplication(LocalTime startAt) { - boolean isExist = reservationTimeRepository.isExistReservationTimeByStartAt(startAt); - if (isExist) { - throw new DuplicatedException("[ERROR] 중복되는 시간은 추가할 수 없습니다."); - } + public ReservationTime saveReservationTime(ReservationTimeDto timeDto) { + validateDuplication(timeDto.getStartAt()); + ReservationTime time = ReservationTime.from(timeDto); + Optional savedTime = reservationTimeRepository.saveReservationTime(time); + return savedTime.orElseThrow(() -> new BadRequestException("[ERROR] 데이터가 저장되지 않았습니다.")); } public ReservationTime findReservationTime(long id) { - return reservationTimeRepository.findReservationById(id) - .orElseThrow(() -> new BadRequestException("[ERROR] 데이터가 저장되지 않습니다.")); + validateExistence(id); + Optional time = reservationTimeRepository.findReservationById(id); + return time.orElseThrow(() -> new NotFoundException("[ERROR] 존재하지 않는 데이터입니다.")); } public void deleteReservationTime(long id) { - validate(id); - reservationTimeRepository.deleteReservationTimeById(id); - } - - private void validate(Long id) { validateExistence(id); validateDependence(id); + reservationTimeRepository.deleteReservationTimeById(id); } - private void validateDependence(Long id) { - boolean isExist = reservationTimeRepository.isExistReservationByTimeId(id); + private void validateDuplication(LocalTime startAt) { + boolean isExist = reservationTimeRepository.isExistReservationTimeByStartAt(startAt); if (isExist) { - throw new BadRequestException("[ERROR] 해당 시간을 사용하고 있는 예약이 있습니다."); + throw new DuplicatedException("[ERROR] 중복된 시간은 추가할 수 없습니다."); } } @@ -67,4 +57,11 @@ private void validateExistence(Long id) { throw new NotFoundException("[ERROR] 존재하지 않는 시간입니다."); } } + + private void validateDependence(Long id) { + boolean isExist = reservationTimeRepository.isExistReservationByTimeId(id); + if (isExist) { + throw new BadRequestException("[ERROR] 해당 시간을 사용하고 있는 예약이 있습니다."); + } + } } diff --git a/src/main/java/roomescape/service/ThemeService.java b/src/main/java/roomescape/service/ThemeService.java index 8bffd55f65..d665cd7362 100644 --- a/src/main/java/roomescape/service/ThemeService.java +++ b/src/main/java/roomescape/service/ThemeService.java @@ -2,12 +2,15 @@ import org.springframework.stereotype.Service; import roomescape.exception.BadRequestException; +import roomescape.exception.DuplicatedException; +import roomescape.exception.NotFoundException; import roomescape.model.Theme; import roomescape.repository.ThemeRepository; import roomescape.service.dto.ThemeDto; import java.time.LocalDate; import java.util.List; +import java.util.Optional; @Service public class ThemeService { @@ -26,12 +29,14 @@ public List findAllThemes() { } public Theme saveTheme(ThemeDto themeDto) { + validateDuplication(themeDto.getName()); Theme theme = Theme.from(themeDto); - return themeRepository.saveTheme(theme) - .orElseThrow(() -> new BadRequestException("[ERROR] 데이터가 저장되지 않습니다.")); + Optional savedTheme = themeRepository.saveTheme(theme); + return savedTheme.orElseThrow(() -> new BadRequestException("[ERROR] 데이터가 저장되지 않았습니다.")); } public void deleteTheme(long id) { + validateExistence(id); themeRepository.deleteThemeById(id); } @@ -40,4 +45,18 @@ public List findPopularThemes() { LocalDate endDate = LocalDate.now().minusDays(1); return themeRepository.findThemeRankingByDate(startDate, endDate, COUNT_OF_RANKING); } + + private void validateDuplication(String name) { + boolean isExistName = themeRepository.isExistThemeByName(name); + if (isExistName) { + throw new DuplicatedException("[ERROR] 테마의 이름은 중복될 수 없습니다."); + } + } + + private void validateExistence(Long id) { + boolean isNotExist = !themeRepository.isExistThemeById(id); + if (isNotExist) { + throw new NotFoundException("[ERROR] 존재하지 않는 테마입니다."); + } + } } diff --git a/src/test/java/roomescape/controller/request/ReservationRequestTest.java b/src/test/java/roomescape/controller/request/ReservationRequestTest.java index a5dd5d6c0c..f23ba87914 100644 --- a/src/test/java/roomescape/controller/request/ReservationRequestTest.java +++ b/src/test/java/roomescape/controller/request/ReservationRequestTest.java @@ -1,11 +1,9 @@ package roomescape.controller.request; import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.NullAndEmptySource; -import org.junit.jupiter.params.provider.NullSource; import org.junit.jupiter.params.provider.ValueSource; import roomescape.exception.BadRequestException; diff --git a/src/test/java/roomescape/model/ReservationTest.java b/src/test/java/roomescape/model/ReservationTest.java index 4fe9cd8758..73d316a4bf 100644 --- a/src/test/java/roomescape/model/ReservationTest.java +++ b/src/test/java/roomescape/model/ReservationTest.java @@ -5,10 +5,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; import org.junit.jupiter.params.provider.NullAndEmptySource; -import org.junit.jupiter.params.provider.NullSource; import org.junit.jupiter.params.provider.ValueSource; -import roomescape.controller.request.ReservationRequest; -import roomescape.exception.BadRequestException; import roomescape.service.dto.ReservationDto; import java.time.LocalDate; diff --git a/src/test/java/roomescape/service/ReservationServiceTest.java b/src/test/java/roomescape/service/ReservationServiceTest.java index 0f2719e5a7..22cd05b3ad 100644 --- a/src/test/java/roomescape/service/ReservationServiceTest.java +++ b/src/test/java/roomescape/service/ReservationServiceTest.java @@ -66,28 +66,6 @@ void should_save_reservation() { assertThat(reservationService.findAllReservations()).hasSize(INITIAL_RESERVATION_COUNT + 1); } - @DisplayName("예약을 삭제한다.") - @Test - void should_delete_reservation() { - reservationService.deleteReservation(1L); - assertThat(reservationService.findAllReservations()).hasSize(INITIAL_RESERVATION_COUNT - 1); - } - - @DisplayName("존재하는 예약을 삭제하려 하면 예외가 발생하지 않는다.") - @Test - void should_not_throw_exception_when_exist_reservation_time() { - assertThatCode(() -> reservationService.deleteReservation(1L)) - .doesNotThrowAnyException(); - } - - @DisplayName("존재하지 않는 예약을 삭제하려 하면 예외가 발생한다.") - @Test - void should_throw_exception_when_not_exist_reservation_time() { - assertThatThrownBy(() -> reservationService.deleteReservation(999L)) - .isInstanceOf(NotFoundException.class) - .hasMessage("[ERROR] 존재하지 않는 예약입니다."); - } - @DisplayName("현재 이전으로 예약하려 하면 예외가 발생한다.") @Test void should_throw_exception_when_previous_date() { @@ -122,6 +100,28 @@ void should_throw_exception_when_add_exist_reservation() { .hasMessage("[ERROR] 중복되는 예약은 추가할 수 없습니다."); } + @DisplayName("예약을 삭제한다.") + @Test + void should_delete_reservation() { + reservationService.deleteReservation(1L); + assertThat(reservationService.findAllReservations()).hasSize(INITIAL_RESERVATION_COUNT - 1); + } + + @DisplayName("존재하는 예약을 삭제하려 하면 예외가 발생하지 않는다.") + @Test + void should_not_throw_exception_when_exist_reservation_time() { + assertThatCode(() -> reservationService.deleteReservation(1L)) + .doesNotThrowAnyException(); + } + + @DisplayName("존재하지 않는 예약을 삭제하려 하면 예외가 발생한다.") + @Test + void should_throw_exception_when_not_exist_reservation_time() { + assertThatThrownBy(() -> reservationService.deleteReservation(999L)) + .isInstanceOf(NotFoundException.class) + .hasMessage("[ERROR] 존재하지 않는 예약입니다."); + } + @DisplayName("예약 가능 상태를 담은 시간 정보를 반환한다.") @Test void should_return_times_with_book_state() { diff --git a/src/test/java/roomescape/service/ReservationTimeServiceTest.java b/src/test/java/roomescape/service/ReservationTimeServiceTest.java index c1499a3be6..188e0e92a9 100644 --- a/src/test/java/roomescape/service/ReservationTimeServiceTest.java +++ b/src/test/java/roomescape/service/ReservationTimeServiceTest.java @@ -55,7 +55,15 @@ void should_find_reservation_time_by_id() { assertThat(actual).isEqualTo(expected); } - @DisplayName("예약 시간을 추가한다") + @DisplayName("존재하지 않는 시간을 조회하려는 경우 예외가 발생한다.") + @Test + void should_throw_exception_when_not_exist_time() { + assertThatThrownBy(() -> reservationTimeService.findReservationTime(999L)) + .isInstanceOf(NotFoundException.class) + .hasMessage("[ERROR] 존재하지 않는 시간입니다."); + } + + @DisplayName("예약 시간을 추가한다.") @Test void should_save_reservation_time() { ReservationTimeDto timeDto = new ReservationTimeDto(LocalTime.of(4, 0)); @@ -63,6 +71,15 @@ void should_save_reservation_time() { assertThat(reservationTimeService.findAllReservationTimes()).hasSize(INITIAL_TIME_COUNT + 1); } + @DisplayName("중복된 시간을 추가하려는 경우 예외가 발생한다.") + @Test + void should_throw_exception_when_duplicated_time() { + ReservationTimeDto timeDto = new ReservationTimeDto(LocalTime.of(1, 0)); + assertThatThrownBy(() -> reservationTimeService.saveReservationTime(timeDto)) + .isInstanceOf(DuplicatedException.class) + .hasMessage("[ERROR] 중복된 시간은 추가할 수 없습니다."); + } + @DisplayName("예약 시간을 삭제한다.") @Test void should_delete_reservation_time() { @@ -99,6 +116,6 @@ void should_throw_exception_when_add_exist_time() { ReservationTimeDto timeDto = new ReservationTimeDto(LocalTime.of(1, 0)); assertThatThrownBy(() -> reservationTimeService.saveReservationTime(timeDto)) .isInstanceOf(DuplicatedException.class) - .hasMessage("[ERROR] 중복되는 시간은 추가할 수 없습니다."); + .hasMessage("[ERROR] 중복된 시간은 추가할 수 없습니다."); } } diff --git a/src/test/java/roomescape/service/ThemeServiceTest.java b/src/test/java/roomescape/service/ThemeServiceTest.java index b3d3de0a47..f44b24d925 100644 --- a/src/test/java/roomescape/service/ThemeServiceTest.java +++ b/src/test/java/roomescape/service/ThemeServiceTest.java @@ -3,6 +3,8 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import roomescape.exception.DuplicatedException; +import roomescape.exception.NotFoundException; import roomescape.model.Theme; import roomescape.repository.ThemeRepository; import roomescape.repository.dao.ReservationDao; @@ -17,6 +19,7 @@ import java.util.List; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; class ThemeServiceTest { @@ -50,6 +53,15 @@ void should_save_theme() { assertThat(themeService.findAllThemes()).hasSize(INITIAL_THEME_COUNT + 1); } + @DisplayName("중복된 이름의 테마를 저장하려는 경우 예외가 발생한다.") + @Test + void should_throw_exception_when_duplicated_name() { + ThemeDto themeDto = new ThemeDto("n1", "d", "t"); + assertThatThrownBy(() -> themeService.saveTheme(themeDto)) + .isInstanceOf(DuplicatedException.class) + .hasMessage("[ERROR] 테마의 이름은 중복될 수 없습니다."); + } + @DisplayName("테마를 삭제한다.") @Test void should_delete_theme() { @@ -57,6 +69,14 @@ void should_delete_theme() { assertThat(themeService.findAllThemes()).hasSize(INITIAL_THEME_COUNT - 1); } + @DisplayName("존재하지 않는 테마를 삭제하려는 경우 예외가 발생한다.") + @Test + void should_throw_exception_when_not_exist_id() { + assertThatThrownBy(() -> themeService.deleteTheme(999L)) + .isInstanceOf(NotFoundException.class) + .hasMessage("[ERROR] 존재하지 않는 테마입니다."); + } + @DisplayName("최근 일주일 간 가장 인기 있는 테마 10개를 조회한다.") @Test void should_find_popular_theme_of_week() { // TODO: test case 구체화 diff --git a/src/test/java/roomescape/service/fakedao/FakeThemeDao.java b/src/test/java/roomescape/service/fakedao/FakeThemeDao.java index 38f066aa78..81dd61f6b9 100644 --- a/src/test/java/roomescape/service/fakedao/FakeThemeDao.java +++ b/src/test/java/roomescape/service/fakedao/FakeThemeDao.java @@ -39,6 +39,16 @@ public void deleteById(long id) { themes.remove(targetTheme); } + @Override + public Boolean isExistById(long id) { + return themes.stream().anyMatch(theme -> theme.getId() == id); + } + + @Override + public Boolean isExistByName(String name) { + return themes.stream().anyMatch(theme -> theme.getName().equals(name)); + } + @Override public Optional findById(long id) { return themes.stream() From a85a0a0cf9b965b2de7ee9541eca7cc1dc1a596f Mon Sep 17 00:00:00 2001 From: SCY Date: Tue, 7 May 2024 11:25:23 +0900 Subject: [PATCH 72/74] =?UTF-8?q?fix(ReservationService):=20=EC=98=88?= =?UTF-8?q?=EC=95=BD=EC=9D=98=20=EC=A4=91=EB=B3=B5=20=EA=B2=80=EC=A6=9D=20?= =?UTF-8?q?=EC=8B=9C=20=ED=85=8C=EB=A7=88=20=EA=B2=80=EC=A6=9D=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/roomescape/repository/ReservationRepository.java | 4 ++-- .../roomescape/repository/dao/JdbcReservationDao.java | 6 +++--- .../java/roomescape/repository/dao/ReservationDao.java | 2 +- src/main/java/roomescape/service/ReservationService.java | 6 +++--- .../roomescape/repository/ReservationRepositoryTest.java | 8 ++++---- .../roomescape/repository/dao/ReservationDaoTest.java | 8 ++++---- .../java/roomescape/service/ReservationServiceTest.java | 2 +- .../roomescape/service/fakedao/FakeReservationDao.java | 6 ++++-- .../service/fakedao/FakeReservationDaoTest.java | 4 ++-- 9 files changed, 24 insertions(+), 22 deletions(-) diff --git a/src/main/java/roomescape/repository/ReservationRepository.java b/src/main/java/roomescape/repository/ReservationRepository.java index 2fc4385851..24f4caa532 100644 --- a/src/main/java/roomescape/repository/ReservationRepository.java +++ b/src/main/java/roomescape/repository/ReservationRepository.java @@ -45,8 +45,8 @@ public Optional findThemeById(long id) { return themeDao.findById(id); } - public boolean isExistReservationByDateAndTimeId(LocalDate date, long timeId) { - return reservationDao.isExistByDateAndTimeId(date, timeId); + public boolean isExistReservationByDateAndTimeIdAndThemeId(LocalDate date, long timeId, long themeId) { + return reservationDao.isExistByDateAndTimeIdAndThemeId(date, timeId, themeId); } public Reservation saveReservation(Reservation reservation) { diff --git a/src/main/java/roomescape/repository/dao/JdbcReservationDao.java b/src/main/java/roomescape/repository/dao/JdbcReservationDao.java index bd041fe2af..849e527091 100644 --- a/src/main/java/roomescape/repository/dao/JdbcReservationDao.java +++ b/src/main/java/roomescape/repository/dao/JdbcReservationDao.java @@ -104,8 +104,8 @@ public Boolean isExistByTimeId(long timeId) { } @Override - public Boolean isExistByDateAndTimeId(LocalDate date, long timeId) { - String sql = "select exists (select id from reservation where date = ? and time_id = ?)"; - return jdbcTemplate.queryForObject(sql, Boolean.class, date, timeId); + public Boolean isExistByDateAndTimeIdAndThemeId(LocalDate date, long timeId, long themeId) { + String sql = "select exists (select id from reservation where date = ? and time_id = ? and theme_id = ?)"; + return jdbcTemplate.queryForObject(sql, Boolean.class, date, timeId, themeId); } } diff --git a/src/main/java/roomescape/repository/dao/ReservationDao.java b/src/main/java/roomescape/repository/dao/ReservationDao.java index 4085a6b509..004cc4f94b 100644 --- a/src/main/java/roomescape/repository/dao/ReservationDao.java +++ b/src/main/java/roomescape/repository/dao/ReservationDao.java @@ -24,5 +24,5 @@ public interface ReservationDao { Boolean isExistByTimeId(long timeId); - Boolean isExistByDateAndTimeId(LocalDate date, long timeId); + Boolean isExistByDateAndTimeIdAndThemeId(LocalDate date, long timeId, long themeId); } diff --git a/src/main/java/roomescape/service/ReservationService.java b/src/main/java/roomescape/service/ReservationService.java index 7b51f9777a..215aaf250c 100644 --- a/src/main/java/roomescape/service/ReservationService.java +++ b/src/main/java/roomescape/service/ReservationService.java @@ -38,7 +38,7 @@ public Reservation saveReservation(ReservationDto reservationDto) { LocalDate date = reservationDto.getDate(); validateIsFuture(date, time.getStartAt()); - validateDuplication(date, time.getId()); + validateDuplication(date, time.getId(), theme.getId()); Reservation reservation = Reservation.from(reservationDto, time, theme); return reservationRepository.saveReservation(reservation); @@ -90,8 +90,8 @@ private void validateIsFuture(LocalDate date, LocalTime time) { } } - private void validateDuplication(LocalDate date, long timeId) { - boolean isExist = reservationRepository.isExistReservationByDateAndTimeId(date, timeId); + private void validateDuplication(LocalDate date, long timeId, long themeId) { + boolean isExist = reservationRepository.isExistReservationByDateAndTimeIdAndThemeId(date, timeId, themeId); if (isExist) { throw new DuplicatedException("[ERROR] 중복되는 예약은 추가할 수 없습니다."); } diff --git a/src/test/java/roomescape/repository/ReservationRepositoryTest.java b/src/test/java/roomescape/repository/ReservationRepositoryTest.java index 68fdf0ef54..f4ca74eaf5 100644 --- a/src/test/java/roomescape/repository/ReservationRepositoryTest.java +++ b/src/test/java/roomescape/repository/ReservationRepositoryTest.java @@ -111,17 +111,17 @@ void should_find_theme_by_id() { assertThat(time).hasValue(new Theme(1, "n1", "d1", "t1")); } - @DisplayName("특정 날짜와 시간을 가진 예약이 존재하는 경우 참을 반환한다.") + @DisplayName("특정 날짜와 시간과 테마를 가진 예약이 존재하는 경우 참을 반환한다.") @Test void should_return_true_when_exist_reservation_by_date_and_timeId() { - boolean isExist = reservationRepository.isExistReservationByDateAndTimeId(LocalDate.of(2000, 1, 1), 1); + boolean isExist = reservationRepository.isExistReservationByDateAndTimeIdAndThemeId(LocalDate.of(2000, 1, 1), 1L, 1L); assertThat(isExist).isTrue(); } - @DisplayName("특정 날짜와 시간을 가진 예약이 존재하지 않는 경우 거짓을 반환한다.") + @DisplayName("특정 날짜와 시간과 테마를 가진 예약이 존재하지 않는 경우 거짓을 반환한다.") @Test void should_return_false_when_not_exist_reservation_by_date_and_timeId() { - boolean isExist = reservationRepository.isExistReservationByDateAndTimeId(LocalDate.of(9999, 1, 1), 1); + boolean isExist = reservationRepository.isExistReservationByDateAndTimeIdAndThemeId(LocalDate.of(9999, 1, 1), 1L, 1L); assertThat(isExist).isFalse(); } diff --git a/src/test/java/roomescape/repository/dao/ReservationDaoTest.java b/src/test/java/roomescape/repository/dao/ReservationDaoTest.java index 71395a3d0f..a5e96fe90c 100644 --- a/src/test/java/roomescape/repository/dao/ReservationDaoTest.java +++ b/src/test/java/roomescape/repository/dao/ReservationDaoTest.java @@ -168,17 +168,17 @@ void should_return_false_when_not_exist_timeId() { assertThat(isExist).isFalse(); } - @DisplayName("특정 date와 time_id를 가진 예약이 존재하면 참을 반환한다.") + @DisplayName("특정 date와 time_id와 theme_id를 가진 예약이 존재하면 참을 반환한다.") @Test void should_return_true_when_exist_date_and_timeId() { - boolean isExist = reservationDao.isExistByDateAndTimeId(LocalDate.of(2000, 1, 1), 1); + boolean isExist = reservationDao.isExistByDateAndTimeIdAndThemeId(LocalDate.of(2000, 1, 1), 1L, 1L); assertThat(isExist).isTrue(); } - @DisplayName("특정 date와 time_id를 가진 예약이 존재하지 않으면 거짓을 반환한다.") + @DisplayName("특정 date와 time_id와 theme_id를 가진 예약이 존재하지 않으면 거짓을 반환한다.") @Test void should_return_false_when_not_exist_date_and_timeId() { - boolean isExist = reservationDao.isExistByDateAndTimeId(LocalDate.of(2000, 1, 1), 999); + boolean isExist = reservationDao.isExistByDateAndTimeIdAndThemeId(LocalDate.of(2000, 1, 1), 999L, 1L); assertThat(isExist).isFalse(); } } diff --git a/src/test/java/roomescape/service/ReservationServiceTest.java b/src/test/java/roomescape/service/ReservationServiceTest.java index 22cd05b3ad..dd2a6307cb 100644 --- a/src/test/java/roomescape/service/ReservationServiceTest.java +++ b/src/test/java/roomescape/service/ReservationServiceTest.java @@ -94,7 +94,7 @@ void should_not_throw_exception_when_later_date() { @DisplayName("날짜와 시간이 중복되는 예약을 추가하려 할 때 예외가 발생한다.") @Test void should_throw_exception_when_add_exist_reservation() { - ReservationDto reservationDto = new ReservationDto("n", LocalDate.of(9999, 9, 9), 1L, 2L); + ReservationDto reservationDto = new ReservationDto("n", LocalDate.of(9999, 9, 9), 1L, 1L); assertThatThrownBy(() -> reservationService.saveReservation(reservationDto)) .isInstanceOf(DuplicatedException.class) .hasMessage("[ERROR] 중복되는 예약은 추가할 수 없습니다."); diff --git a/src/test/java/roomescape/service/fakedao/FakeReservationDao.java b/src/test/java/roomescape/service/fakedao/FakeReservationDao.java index 56ade073f2..b050c6bb9a 100644 --- a/src/test/java/roomescape/service/fakedao/FakeReservationDao.java +++ b/src/test/java/roomescape/service/fakedao/FakeReservationDao.java @@ -101,8 +101,10 @@ public Boolean isExistByTimeId(long timeId) { } @Override - public Boolean isExistByDateAndTimeId(LocalDate date, long timeId) { + public Boolean isExistByDateAndTimeIdAndThemeId(LocalDate date, long timeId, long themeId) { return reservations.stream() - .anyMatch(reservation -> reservation.getDate().isEqual(date) && reservation.getTimeId() == timeId); + .anyMatch(reservation -> reservation.getDate().isEqual(date) + && reservation.getTimeId() == timeId + && reservation.getThemeId() == themeId); } } \ No newline at end of file diff --git a/src/test/java/roomescape/service/fakedao/FakeReservationDaoTest.java b/src/test/java/roomescape/service/fakedao/FakeReservationDaoTest.java index ef482c2657..8e6574c668 100644 --- a/src/test/java/roomescape/service/fakedao/FakeReservationDaoTest.java +++ b/src/test/java/roomescape/service/fakedao/FakeReservationDaoTest.java @@ -134,14 +134,14 @@ void should_return_false_when_not_exist_timeId() { @DisplayName("해당 날짜와 timeId를 가진 예약이 존재하면 참을 반환한다.") @Test void should_return_true_when_exist_date_and_timeId() { - Boolean isExist = fakeReservationDao.isExistByDateAndTimeId(LocalDate.now(), 1); + Boolean isExist = fakeReservationDao.isExistByDateAndTimeIdAndThemeId(LocalDate.now(), 1L, 1L); assertThat(isExist).isTrue(); } @DisplayName("해당 날짜와 timeId를 가진 예약이 존재하지 않으면 거짓을 반환한다.") @Test void should_return_false_when_not_exist_date_and_timeId() { - Boolean isExist = fakeReservationDao.isExistByDateAndTimeId(LocalDate.now(), 999); + Boolean isExist = fakeReservationDao.isExistByDateAndTimeIdAndThemeId(LocalDate.now(), 999L, 1L); assertThat(isExist).isFalse(); } } \ No newline at end of file From 6853ef7bff75a87dc901cc5d850bf7958c4d3e02 Mon Sep 17 00:00:00 2001 From: SCY Date: Tue, 7 May 2024 13:06:06 +0900 Subject: [PATCH 73/74] =?UTF-8?q?refactor(sql):=20UNIQUE=20=EC=98=B5?= =?UTF-8?q?=EC=85=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MemberReservationTimeResponse.java | 9 +++ src/main/resources/schema.sql | 5 +- .../controller/ReservationControllerTest.java | 19 ++++--- .../controller/ThemeControllerTest.java | 57 ++++++++++--------- 4 files changed, 53 insertions(+), 37 deletions(-) diff --git a/src/main/java/roomescape/controller/response/MemberReservationTimeResponse.java b/src/main/java/roomescape/controller/response/MemberReservationTimeResponse.java index 979ff0d156..e27bb55a87 100644 --- a/src/main/java/roomescape/controller/response/MemberReservationTimeResponse.java +++ b/src/main/java/roomescape/controller/response/MemberReservationTimeResponse.java @@ -28,4 +28,13 @@ public LocalTime getStartAt() { public boolean getIsBooked() { return isBooked; } + + @Override + public String toString() { + return "MemberReservationTimeResponse{" + + "timeId=" + timeId + + ", startAt=" + startAt + + ", isBooked=" + isBooked + + '}'; + } } diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql index 99a882e1ba..3e03a5fe1a 100644 --- a/src/main/resources/schema.sql +++ b/src/main/resources/schema.sql @@ -1,14 +1,14 @@ CREATE TABLE reservation_time ( id BIGINT NOT NULL AUTO_INCREMENT, - start_at VARCHAR(255) NOT NULL, + start_at VARCHAR(255) UNIQUE NOT NULL, PRIMARY KEY (id) ); CREATE TABLE theme ( id BIGINT NOT NULL AUTO_INCREMENT, - name VARCHAR(255) NOT NULL, + name VARCHAR(255) UNIQUE NOT NULL, description VARCHAR(255) NOT NULL, thumbnail VARCHAR(255) NOT NULL, PRIMARY KEY (id) @@ -21,6 +21,7 @@ CREATE TABLE reservation date VARCHAR(255) NOT NULL, time_id BIGINT, theme_id BIGINT, + UNIQUE (date, time_id, theme_id), PRIMARY KEY (id), FOREIGN KEY (time_id) REFERENCES reservation_time (id), FOREIGN KEY (theme_id) REFERENCES theme (id) diff --git a/src/test/java/roomescape/controller/ReservationControllerTest.java b/src/test/java/roomescape/controller/ReservationControllerTest.java index 29338089df..b2d15ca1ee 100644 --- a/src/test/java/roomescape/controller/ReservationControllerTest.java +++ b/src/test/java/roomescape/controller/ReservationControllerTest.java @@ -2,6 +2,7 @@ import io.restassured.RestAssured; import io.restassured.http.ContentType; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -54,12 +55,10 @@ void setUp() { IntStream.range(1, 6).forEach(i -> insertReservationTime(i + ":00")); IntStream.range(0, 20).forEach(i -> insertTheme("n" + i, "d" + i, "t" + i)); - LocalDate date = LocalDate.now().minusDays(1); - IntStream.range(0, 1).forEach(i -> insertReservation("n" + i, date, 1, 1)); - IntStream.range(0, 2).forEach(i -> insertReservation("n" + i, date, 1, 2)); - IntStream.range(0, 3).forEach(i -> insertReservation("n" + i, date, 1, 3)); - IntStream.range(0, 4).forEach(i -> insertReservation("n" + i, date, 2, 1)); - IntStream.range(0, 5).forEach(i -> insertReservation("n" + i, date, 2, 2)); + LocalDate now = LocalDate.now(); + IntStream.range(0, 5).forEach(i -> insertReservation("n", now.minusDays(i), 1L, 1L)); + IntStream.range(0, 5).forEach(i -> insertReservation("n", now.minusDays(i), 2L, 1L)); + IntStream.range(0, 5).forEach(i -> insertReservation("n", now.minusDays(i), 3L, 1L)); } private void initDatabase() { @@ -142,12 +141,18 @@ void should_get_reservations_with_book_state_by_date_and_theme() { .statusCode(200) .extract().jsonPath().getList(".", MemberReservationTimeResponse.class); + System.out.println(times); assertThat(times).hasSize(INITIAL_TIME_COUNT); assertThat(times.get(0).getIsBooked()).isTrue(); + assertThat(times.get(0).getTimeId()).isEqualTo(1); assertThat(times.get(1).getIsBooked()).isTrue(); - assertThat(times.get(2).getIsBooked()).isFalse(); + assertThat(times.get(1).getTimeId()).isEqualTo(2); + assertThat(times.get(2).getIsBooked()).isTrue(); + assertThat(times.get(2).getTimeId()).isEqualTo(3); assertThat(times.get(3).getIsBooked()).isFalse(); + assertThat(times.get(3).getTimeId()).isEqualTo(4); assertThat(times.get(4).getIsBooked()).isFalse(); + assertThat(times.get(4).getTimeId()).isEqualTo(5); } private Integer countAllReservations() { diff --git a/src/test/java/roomescape/controller/ThemeControllerTest.java b/src/test/java/roomescape/controller/ThemeControllerTest.java index 53312b57ca..d03c2961a6 100644 --- a/src/test/java/roomescape/controller/ThemeControllerTest.java +++ b/src/test/java/roomescape/controller/ThemeControllerTest.java @@ -51,14 +51,14 @@ public ThemeControllerTest(JdbcTemplate jdbcTemplate) { void setUp() { initDatabase(); IntStream.range(1, 3).forEach(i -> insertReservationTime(i + ":00")); - IntStream.range(0, 20).forEach(i -> insertTheme("n" + i, "d" + i, "t" + i)); - - LocalDate date = LocalDate.now().minusDays(1); - IntStream.range(0, 1).forEach(i -> insertReservation("n" + i, date, 1, 1)); - IntStream.range(0, 2).forEach(i -> insertReservation("n" + i, date, 1, 2)); - IntStream.range(0, 3).forEach(i -> insertReservation("n" + i, date, 1, 3)); - IntStream.range(0, 4).forEach(i -> insertReservation("n" + i, date, 2, 4)); - IntStream.range(0, 5).forEach(i -> insertReservation("n" + i, date, 2, 5)); + IntStream.range(1, 21).forEach(i -> insertTheme("n" + i, "d" + i, "t" + i)); + + LocalDate now = LocalDate.now(); + IntStream.range(1, 2).forEach(i -> insertReservation("n", now.minusDays(i), 1L, 1L)); + IntStream.range(1, 3).forEach(i -> insertReservation("n", now.minusDays(i), 1L, 2L)); + IntStream.range(1, 4).forEach(i -> insertReservation("n", now.minusDays(i), 1L, 3L)); + IntStream.range(1, 5).forEach(i -> insertReservation("n", now.minusDays(i), 2L, 4L)); + IntStream.range(1, 6).forEach(i -> insertReservation("n", now.minusDays(i), 2L, 5L)); } private void initDatabase() { @@ -129,26 +129,7 @@ void should_remove_theme() { assertThat(countAllThemes()).isEqualTo(INITIAL_THEME_COUNT - 1); } - @DisplayName("예약된 전체 테마 개수가 10 이하인 경우 해당 개수만큼의 인기 테마를 인기 순으로 조회한다.") - @Test - void should_find_popular_themes_when_less_than_10() { - List popularThemes = RestAssured.given().log().all() - .when().get("/themes/rank") - .then().log().all() - .statusCode(200) - .extract().jsonPath().getList(".", ThemeResponse.class); - - assertAll(() -> { - assertThat(popularThemes).hasSize(5); - assertThat(popularThemes.get(0).getId()).isEqualTo(5); - assertThat(popularThemes.get(1).getId()).isEqualTo(4); - assertThat(popularThemes.get(2).getId()).isEqualTo(3); - assertThat(popularThemes.get(3).getId()).isEqualTo(2); - assertThat(popularThemes.get(4).getId()).isEqualTo(1); - }); - } - - @DisplayName("예약된 전체 테마 개수가 10 이상인 경우 인기 테마를 인기 순으로 10개 조회한다. 예약 횟수가 같은 경우 theme_id 순으로 조회한다.") + @DisplayName("일주일 간 예약된 테마를 인기 순으로 10개 조회한다. 예약 횟수가 같은 경우 theme_id 오름차순으로 조회한다.") @Test void should_find_popular_themes_when_more_than_10() { LocalDate date = LocalDate.now().minusDays(1); @@ -181,6 +162,26 @@ void should_find_popular_themes_when_more_than_10() { }); } + @DisplayName("예약된 전체 테마 개수가 10 이하인 경우, 해당 개수만큼의 인기 테마를 인기 순으로 조회한다.") + @Test + void should_find_popular_themes_when_less_than_10() { + List popularThemes = RestAssured.given().log().all() + .when().get("/themes/rank") + .then().log().all() + .statusCode(200) + .extract().jsonPath().getList(".", ThemeResponse.class); + + System.out.println(popularThemes); + assertAll(() -> { + assertThat(popularThemes).hasSize(5); + assertThat(popularThemes.get(0).getId()).isEqualTo(5); + assertThat(popularThemes.get(1).getId()).isEqualTo(4); + assertThat(popularThemes.get(2).getId()).isEqualTo(3); + assertThat(popularThemes.get(3).getId()).isEqualTo(2); + assertThat(popularThemes.get(4).getId()).isEqualTo(1); + }); + } + private Integer countAllThemes() { return jdbcTemplate.queryForObject("SELECT count(id) from theme", Integer.class); } From f0bde3157225557bb060331282ac6cb72d99192a Mon Sep 17 00:00:00 2001 From: SCY Date: Tue, 7 May 2024 15:06:29 +0900 Subject: [PATCH 74/74] =?UTF-8?q?refactor(test):=20=EB=B6=88=ED=95=84?= =?UTF-8?q?=EC=9A=94=ED=95=9C=20DirtiesContext=20=EC=96=B4=EB=85=B8?= =?UTF-8?q?=ED=85=8C=EC=9D=B4=EC=85=98=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/roomescape/controller/ReservationControllerTest.java | 3 --- .../roomescape/controller/ReservationTimeControllerTest.java | 3 +-- src/test/java/roomescape/controller/ThemeControllerTest.java | 2 -- .../java/roomescape/repository/ReservationRepositoryTest.java | 2 -- .../roomescape/repository/ReservationTimeRepositoryTest.java | 2 -- src/test/java/roomescape/repository/ThemeRepositoryTest.java | 2 -- .../java/roomescape/repository/dao/DatabaseConnectionTest.java | 2 -- .../java/roomescape/repository/dao/ReservationDaoTest.java | 2 -- .../java/roomescape/repository/dao/ReservationTimeDaoTest.java | 2 -- src/test/java/roomescape/repository/dao/ThemeDaoTest.java | 2 -- 10 files changed, 1 insertion(+), 21 deletions(-) diff --git a/src/test/java/roomescape/controller/ReservationControllerTest.java b/src/test/java/roomescape/controller/ReservationControllerTest.java index b2d15ca1ee..07acab9932 100644 --- a/src/test/java/roomescape/controller/ReservationControllerTest.java +++ b/src/test/java/roomescape/controller/ReservationControllerTest.java @@ -2,7 +2,6 @@ import io.restassured.RestAssured; import io.restassured.http.ContentType; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -10,7 +9,6 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.simple.SimpleJdbcInsert; -import org.springframework.test.annotation.DirtiesContext; import roomescape.controller.request.ReservationRequest; import roomescape.controller.response.MemberReservationTimeResponse; import roomescape.controller.response.ReservationResponse; @@ -24,7 +22,6 @@ import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) -@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) class ReservationControllerTest { private static final int INITIAL_TIME_COUNT = 5; diff --git a/src/test/java/roomescape/controller/ReservationTimeControllerTest.java b/src/test/java/roomescape/controller/ReservationTimeControllerTest.java index 1bd9d0672e..ceeb864266 100644 --- a/src/test/java/roomescape/controller/ReservationTimeControllerTest.java +++ b/src/test/java/roomescape/controller/ReservationTimeControllerTest.java @@ -9,7 +9,6 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.simple.SimpleJdbcInsert; -import org.springframework.test.annotation.DirtiesContext; import roomescape.controller.request.ReservationTimeRequest; import roomescape.model.ReservationTime; @@ -21,7 +20,6 @@ import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) -@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) class ReservationTimeControllerTest { private static final int INITIAL_TIME_COUNT = 2; @@ -47,6 +45,7 @@ void setUp() { private void initDatabase() { jdbcTemplate.execute("ALTER TABLE reservation_time SET REFERENTIAL_INTEGRITY FALSE"); jdbcTemplate.execute("TRUNCATE TABLE reservation_time RESTART IDENTITY"); + jdbcTemplate.execute("TRUNCATE TABLE reservation RESTART IDENTITY"); } private void insertReservationTime(String startAt) { diff --git a/src/test/java/roomescape/controller/ThemeControllerTest.java b/src/test/java/roomescape/controller/ThemeControllerTest.java index d03c2961a6..fc626bd16d 100644 --- a/src/test/java/roomescape/controller/ThemeControllerTest.java +++ b/src/test/java/roomescape/controller/ThemeControllerTest.java @@ -9,7 +9,6 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.simple.SimpleJdbcInsert; -import org.springframework.test.annotation.DirtiesContext; import roomescape.controller.request.ThemeRequest; import roomescape.controller.response.ThemeResponse; @@ -23,7 +22,6 @@ import static org.junit.jupiter.api.Assertions.assertAll; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) -@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) class ThemeControllerTest { private static final int INITIAL_THEME_COUNT = 20; diff --git a/src/test/java/roomescape/repository/ReservationRepositoryTest.java b/src/test/java/roomescape/repository/ReservationRepositoryTest.java index f4ca74eaf5..46f2576f5b 100644 --- a/src/test/java/roomescape/repository/ReservationRepositoryTest.java +++ b/src/test/java/roomescape/repository/ReservationRepositoryTest.java @@ -7,7 +7,6 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.simple.SimpleJdbcInsert; -import org.springframework.test.annotation.DirtiesContext; import roomescape.model.Reservation; import roomescape.model.ReservationTime; import roomescape.model.Theme; @@ -23,7 +22,6 @@ import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) -@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) class ReservationRepositoryTest { private static final int INITIAL_RESERVATION_COUNT = 2; diff --git a/src/test/java/roomescape/repository/ReservationTimeRepositoryTest.java b/src/test/java/roomescape/repository/ReservationTimeRepositoryTest.java index ad611d680a..8949c6f7c8 100644 --- a/src/test/java/roomescape/repository/ReservationTimeRepositoryTest.java +++ b/src/test/java/roomescape/repository/ReservationTimeRepositoryTest.java @@ -7,7 +7,6 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.simple.SimpleJdbcInsert; -import org.springframework.test.annotation.DirtiesContext; import roomescape.model.ReservationTime; import roomescape.service.dto.ReservationTimeDto; @@ -20,7 +19,6 @@ import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) -@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) public class ReservationTimeRepositoryTest { private static final int INITIAL_TIME_COUNT = 2; diff --git a/src/test/java/roomescape/repository/ThemeRepositoryTest.java b/src/test/java/roomescape/repository/ThemeRepositoryTest.java index aeac34b4b0..2f1e13fa99 100644 --- a/src/test/java/roomescape/repository/ThemeRepositoryTest.java +++ b/src/test/java/roomescape/repository/ThemeRepositoryTest.java @@ -7,7 +7,6 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.simple.SimpleJdbcInsert; -import org.springframework.test.annotation.DirtiesContext; import roomescape.model.Theme; import roomescape.service.dto.ThemeDto; @@ -20,7 +19,6 @@ import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) -@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) class ThemeRepositoryTest { private static final int INITIAL_THEME_COUNT = 2; diff --git a/src/test/java/roomescape/repository/dao/DatabaseConnectionTest.java b/src/test/java/roomescape/repository/dao/DatabaseConnectionTest.java index 1303da6572..6d008eae7a 100644 --- a/src/test/java/roomescape/repository/dao/DatabaseConnectionTest.java +++ b/src/test/java/roomescape/repository/dao/DatabaseConnectionTest.java @@ -5,7 +5,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.test.annotation.DirtiesContext; import java.sql.Connection; import java.sql.SQLException; @@ -13,7 +12,6 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThat; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) -@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) class DatabaseConnectionTest { @Autowired diff --git a/src/test/java/roomescape/repository/dao/ReservationDaoTest.java b/src/test/java/roomescape/repository/dao/ReservationDaoTest.java index a5e96fe90c..07b2dcd8c0 100644 --- a/src/test/java/roomescape/repository/dao/ReservationDaoTest.java +++ b/src/test/java/roomescape/repository/dao/ReservationDaoTest.java @@ -7,7 +7,6 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.simple.SimpleJdbcInsert; -import org.springframework.test.annotation.DirtiesContext; import roomescape.repository.dto.ReservationSavedDto; import java.time.LocalDate; @@ -19,7 +18,6 @@ import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) -@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) class ReservationDaoTest { private static final int INITIAL_RESERVATION_COUNT = 2; diff --git a/src/test/java/roomescape/repository/dao/ReservationTimeDaoTest.java b/src/test/java/roomescape/repository/dao/ReservationTimeDaoTest.java index ae6e5512f0..68b25423e8 100644 --- a/src/test/java/roomescape/repository/dao/ReservationTimeDaoTest.java +++ b/src/test/java/roomescape/repository/dao/ReservationTimeDaoTest.java @@ -7,7 +7,6 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.simple.SimpleJdbcInsert; -import org.springframework.test.annotation.DirtiesContext; import roomescape.model.ReservationTime; import roomescape.service.dto.ReservationTimeDto; @@ -20,7 +19,6 @@ import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) -@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) class ReservationTimeDaoTest { private static final int INITIAL_TIME_COUNT = 2; diff --git a/src/test/java/roomescape/repository/dao/ThemeDaoTest.java b/src/test/java/roomescape/repository/dao/ThemeDaoTest.java index d533288ab8..1ce3a89071 100644 --- a/src/test/java/roomescape/repository/dao/ThemeDaoTest.java +++ b/src/test/java/roomescape/repository/dao/ThemeDaoTest.java @@ -7,7 +7,6 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.simple.SimpleJdbcInsert; -import org.springframework.test.annotation.DirtiesContext; import roomescape.model.Theme; import roomescape.service.dto.ThemeDto; @@ -19,7 +18,6 @@ import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) -@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) // TODO: vs BEFORE_EACH class ThemeDaoTest { private static final int INITIAL_THEME_COUNT = 2;