diff --git a/README.md b/README.md index 3aa49f7cc..08500f40f 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,17 @@ - [x] 예약 조회 API 명세를 따라 예약 관리 페이지 로드 시 호출되는 예약 목록 조회 API를 구현한다. - [x] API 명세를 따라 예약 추가 API 와 삭제 API를 구현한다. - [x] 예약 추가와 취소가 잘 동작한다. +- [x] 이상의 요구 사항을 데이터베이스와 연동하도록 한다. + +- [x] 방탈출 시간표에 따라 방탈출 예약 시 시간을 선택하는 방식으로 수정한다. +- [x] API 명세를 따라 시간 관리 API를 구현한다. +- [x] 페이지는 templates/admin/time.html 파일을 이용한다. + +- [x] 기존에 구현한 예약 기능에서 시간을 시간 테이블에 저장된 값만 선택할 수 있도록 수정한다. +- [x] templates/admin/reservation.html 을 사용한다. + +- [x] 레이어드 아키텍처를 적용하여 레이어별 책임과 역할에 따라 클래스를 분리한다. +- [x] 분리한 클래스는 매번 새로 생성하지 않고 스프링 빈으로 등록한다. # API 명세 @@ -27,14 +38,11 @@ { "id": 1, "name": "브라운", - "date": "2023-01-01", - "time": "10:00" - }, - { - "id": 2, - "name": "브라운", - "date": "2023-01-02", - "time": "11:00" + "date": "2023-08-05", + "time": { + "id": 1, + "startAt": "10:00" + } } ] ``` @@ -51,7 +59,7 @@ { "date": "2023-08-05", "name": "브라운", - "time": "15:40" + "timeId": 1 } ``` @@ -66,7 +74,10 @@ "id": 1, "name": "브라운", "date": "2023-08-05", - "time": "15:40" + "time": { + "id": 1, + "startAt": "10:00" + } } ``` @@ -79,3 +90,58 @@ ### Response > HTTP/1.1 200 + +## 시간 추가 API + +### request + +> POST /times HTTP/1.1 +> content-type: application/json + +```JSON +{ + "startAt": "10:00" +} +``` + +### response + +> HTTP/1.1 200 +> Content-Type: application/json + +```JSON +{ + "id": 1, + "startAt": "10:00" +} +``` + +## 시간 조회 API + +### request + +> GET /times HTTP/1.1 + +### response + +> HTTP/1.1 200 +> Content-Type: application/json + +```JSON +[ + { + "id": 1, + "startAt": "10:00" + } +] +``` + +## 시간 삭제 API + +### request + +> DELETE /times/1 HTTP/1.1 + +### response + +> HTTP/1.1 200 diff --git a/src/main/java/roomescape/controller/AdminController.java b/src/main/java/roomescape/controller/AdminController.java index bbdf82348..cbdee6650 100644 --- a/src/main/java/roomescape/controller/AdminController.java +++ b/src/main/java/roomescape/controller/AdminController.java @@ -14,6 +14,11 @@ public String mainPage() { @GetMapping("/reservation") public String reservationPage() { - return "admin/reservation-legacy"; + return "admin/reservation"; + } + + @GetMapping("/time") + public String reservationTimePage() { + return "admin/time"; } } diff --git a/src/main/java/roomescape/controller/ReservationController.java b/src/main/java/roomescape/controller/ReservationController.java index 9b42d79ea..26be3989e 100644 --- a/src/main/java/roomescape/controller/ReservationController.java +++ b/src/main/java/roomescape/controller/ReservationController.java @@ -8,41 +8,31 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import roomescape.domain.Reservation; import roomescape.dto.ReservationRequest; import roomescape.dto.ReservationResponse; -import roomescape.storage.ReservationStorage; +import roomescape.service.ReservationService; @RestController @RequestMapping("/reservations") public class ReservationController { - private final ReservationStorage reservationStorage; + private final ReservationService reservationService; - public ReservationController(ReservationStorage reservationStorage) { - this.reservationStorage = reservationStorage; + public ReservationController(ReservationService reservationService) { + this.reservationService = reservationService; } @PostMapping public ReservationResponse saveReservation(@RequestBody ReservationRequest reservationRequest) { - Reservation reservation = reservationStorage.save(reservationRequest); - return toResponse(reservation); - } - - private ReservationResponse toResponse(Reservation reservation) { - return new ReservationResponse(reservation.getId(), - reservation.getName(), reservation.getDate(), reservation.getTime()); + return reservationService.save(reservationRequest); } @GetMapping public List findAllReservations() { - return reservationStorage.findAllReservations() - .stream() - .map(this::toResponse) - .toList(); + return reservationService.findAll(); } - @DeleteMapping("/{reservationId}") - public void delete(@PathVariable long reservationId) { - reservationStorage.delete(reservationId); + @DeleteMapping("/{id}") + public void delete(@PathVariable long id) { + reservationService.delete(id); } } diff --git a/src/main/java/roomescape/controller/ReservationTimeController.java b/src/main/java/roomescape/controller/ReservationTimeController.java new file mode 100644 index 000000000..21d0e51b7 --- /dev/null +++ b/src/main/java/roomescape/controller/ReservationTimeController.java @@ -0,0 +1,38 @@ +package roomescape.controller; + +import java.util.List; +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.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import roomescape.dto.ReservationTimeRequest; +import roomescape.dto.ReservationTimeResponse; +import roomescape.service.ReservationTimeService; + +@RestController +@RequestMapping("/times") +public class ReservationTimeController { + private final ReservationTimeService reservationTimeService; + + public ReservationTimeController(ReservationTimeService reservationTimeService) { + this.reservationTimeService = reservationTimeService; + } + + @PostMapping + public ReservationTimeResponse save(@RequestBody ReservationTimeRequest reservationTimeRequest) { + return reservationTimeService.save(reservationTimeRequest); + } + + @GetMapping + public List findAll() { + return reservationTimeService.findAll(); + } + + @DeleteMapping("/{id}") + public void delete(@PathVariable long id) { + reservationTimeService.delete(id); + } +} diff --git a/src/main/java/roomescape/domain/Reservation.java b/src/main/java/roomescape/domain/Reservation.java index 0cf802911..004dfd31a 100644 --- a/src/main/java/roomescape/domain/Reservation.java +++ b/src/main/java/roomescape/domain/Reservation.java @@ -3,21 +3,30 @@ import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; +import java.util.Objects; public class Reservation implements Comparable { - private final long id; + private final Long id; private final String name; - private final LocalDateTime dateTime; + private final LocalDate date; + private final ReservationTime time; - public Reservation(long id, String name, LocalDateTime dateTime) { + public Reservation(long id, Reservation reservationBeforeSave) { + this(id, reservationBeforeSave.name, reservationBeforeSave.date, reservationBeforeSave.time); + } + + public Reservation(Long id, String name, LocalDate date, ReservationTime time) { this.id = id; this.name = name; - this.dateTime = dateTime; + this.date = date; + this.time = time; } @Override public int compareTo(Reservation other) { - return dateTime.compareTo(other.dateTime); + LocalDateTime dateTime = LocalDateTime.of(date, time.getStartAt()); + LocalDateTime otherDateTime = LocalDateTime.of(other.date, other.time.getStartAt()); + return dateTime.compareTo(otherDateTime); } public boolean hasSameId(long id) { @@ -33,10 +42,56 @@ public String getName() { } public LocalDate getDate() { - return dateTime.toLocalDate(); + return date; } public LocalTime getTime() { - return dateTime.toLocalTime(); + return time.getStartAt(); + } + + public ReservationTime getReservationTime() { + return time; + } + + @Override + public int hashCode() { + int result = id != null ? id.hashCode() : 0; + result = 31 * result + (name != null ? name.hashCode() : 0); + result = 31 * result + (date != null ? date.hashCode() : 0); + result = 31 * result + (time != null ? time.hashCode() : 0); + return result; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + Reservation that = (Reservation) o; + + if (!Objects.equals(id, that.id)) { + return false; + } + if (!Objects.equals(name, that.name)) { + return false; + } + if (!Objects.equals(date, that.date)) { + return false; + } + return Objects.equals(time, that.time); + } + + @Override + public String toString() { + return "Reservation{" + + "id=" + id + + ", name='" + name + '\'' + + ", date=" + date + + ", time=" + time + + '}'; } } diff --git a/src/main/java/roomescape/domain/ReservationTime.java b/src/main/java/roomescape/domain/ReservationTime.java new file mode 100644 index 000000000..8b54f99f8 --- /dev/null +++ b/src/main/java/roomescape/domain/ReservationTime.java @@ -0,0 +1,58 @@ +package roomescape.domain; + +import java.time.LocalTime; +import java.util.Objects; + +public class ReservationTime { + private final Long id; + private final LocalTime startAt; + + public ReservationTime(LocalTime startAt) { + this(null, startAt); + } + + public ReservationTime(Long id, LocalTime startAt) { + this.id = id; + this.startAt = startAt; + } + + public Long getId() { + return id; + } + + public LocalTime getStartAt() { + return startAt; + } + + @Override + public int hashCode() { + int result = id != null ? id.hashCode() : 0; + result = 31 * result + (startAt != null ? startAt.hashCode() : 0); + return result; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + ReservationTime that = (ReservationTime) o; + + if (!Objects.equals(id, that.id)) { + return false; + } + return Objects.equals(startAt, that.startAt); + } + + @Override + public String toString() { + return "ReservationTime{" + + "id=" + id + + ", startAt=" + startAt + + '}'; + } +} diff --git a/src/main/java/roomescape/dto/ReservationRequest.java b/src/main/java/roomescape/dto/ReservationRequest.java index 926358e1d..ad5cb41a2 100644 --- a/src/main/java/roomescape/dto/ReservationRequest.java +++ b/src/main/java/roomescape/dto/ReservationRequest.java @@ -1,7 +1,6 @@ package roomescape.dto; import java.time.LocalDate; -import java.time.LocalTime; -public record ReservationRequest(LocalDate date, String name, LocalTime time) { +public record ReservationRequest(LocalDate date, String name, long timeId) { } diff --git a/src/main/java/roomescape/dto/ReservationResponse.java b/src/main/java/roomescape/dto/ReservationResponse.java index 6e9d6cfd3..d9980c55f 100644 --- a/src/main/java/roomescape/dto/ReservationResponse.java +++ b/src/main/java/roomescape/dto/ReservationResponse.java @@ -1,7 +1,6 @@ package roomescape.dto; import java.time.LocalDate; -import java.time.LocalTime; -public record ReservationResponse(long id, String name, LocalDate date, LocalTime time) { +public record ReservationResponse(long id, String name, LocalDate date, ReservationTimeResponse time) { } diff --git a/src/main/java/roomescape/dto/ReservationTimeRequest.java b/src/main/java/roomescape/dto/ReservationTimeRequest.java new file mode 100644 index 000000000..5cb43c58e --- /dev/null +++ b/src/main/java/roomescape/dto/ReservationTimeRequest.java @@ -0,0 +1,6 @@ +package roomescape.dto; + +import java.time.LocalTime; + +public record ReservationTimeRequest(LocalTime startAt) { +} diff --git a/src/main/java/roomescape/dto/ReservationTimeResponse.java b/src/main/java/roomescape/dto/ReservationTimeResponse.java new file mode 100644 index 000000000..2334e40c2 --- /dev/null +++ b/src/main/java/roomescape/dto/ReservationTimeResponse.java @@ -0,0 +1,6 @@ +package roomescape.dto; + +import java.time.LocalTime; + +public record ReservationTimeResponse(long id, LocalTime startAt) { +} diff --git a/src/main/java/roomescape/repository/JdbcTemplateReservationRepository.java b/src/main/java/roomescape/repository/JdbcTemplateReservationRepository.java new file mode 100644 index 000000000..7884d19fd --- /dev/null +++ b/src/main/java/roomescape/repository/JdbcTemplateReservationRepository.java @@ -0,0 +1,82 @@ +package roomescape.repository; + +import java.sql.Date; +import java.sql.PreparedStatement; +import java.time.LocalDate; +import java.time.LocalTime; +import java.util.List; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.support.GeneratedKeyHolder; +import org.springframework.jdbc.support.KeyHolder; +import org.springframework.stereotype.Repository; +import roomescape.domain.Reservation; +import roomescape.domain.ReservationTime; +import roomescape.dto.ReservationRequest; + +@Repository +public class JdbcTemplateReservationRepository implements ReservationRepository { + private final JdbcTemplate jdbcTemplate; + + public JdbcTemplateReservationRepository(JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } + + @Override + public Reservation save(ReservationRequest reservationRequest) { + ReservationTime reservationTime = findReservationTime(reservationRequest); + Reservation reservation = new Reservation(null, reservationRequest.name(), reservationRequest.date(), + reservationTime); + KeyHolder keyHolder = new GeneratedKeyHolder(); + save(reservation, keyHolder); + long id = keyHolder.getKey().longValue(); + return new Reservation(id, reservation); + } + + private ReservationTime findReservationTime(ReservationRequest reservationRequest) { + String reservationTimeSelectSql = "select * from reservation_time where id = ?"; + return jdbcTemplate.queryForObject(reservationTimeSelectSql, (rs, rowNum) -> { + long id = rs.getLong(1); + LocalTime startAt = rs.getTime(2).toLocalTime(); + return new ReservationTime(id, startAt); + }, reservationRequest.timeId()); + } + + private void save(Reservation reservation, KeyHolder keyHolder) { + jdbcTemplate.update(con -> { + String sql = "insert into reservation(name,date,time_id) values ( ?,?,? )"; + PreparedStatement preparedStatement = con.prepareStatement(sql, new String[]{"id"}); + preparedStatement.setString(1, reservation.getName()); + preparedStatement.setDate(2, Date.valueOf(reservation.getDate())); + preparedStatement.setLong(3, reservation.getReservationTime().getId()); + return preparedStatement; + }, keyHolder); + } + + @Override + public List findAll() { + String query = "SELECT " + + " r.id as reservation_id," + + " r.name," + + " r.date," + + " t.id as time_id," + + " t.start_at as time_value" + + " FROM reservation as r" + + " inner join reservation_time as t" + + " on r.time_id = t.id"; + return jdbcTemplate.query(query, + (rs, rowNum) -> { + long id = rs.getLong(1); + String name = rs.getString(2); + LocalDate date = rs.getDate(3).toLocalDate(); + long timeId = rs.getLong(4); + LocalTime startAt = rs.getTime(5).toLocalTime(); + ReservationTime reservationTime = new ReservationTime(timeId, startAt); + return new Reservation(id, name, date, reservationTime); + }); + } + + @Override + public void delete(long id) { + jdbcTemplate.update("delete from reservation where id = ?", id); + } +} diff --git a/src/main/java/roomescape/repository/JdbcTemplateReservationTimeRepository.java b/src/main/java/roomescape/repository/JdbcTemplateReservationTimeRepository.java new file mode 100644 index 000000000..639db36ea --- /dev/null +++ b/src/main/java/roomescape/repository/JdbcTemplateReservationTimeRepository.java @@ -0,0 +1,51 @@ +package roomescape.repository; + +import java.sql.PreparedStatement; +import java.sql.Time; +import java.time.LocalTime; +import java.util.List; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.support.GeneratedKeyHolder; +import org.springframework.jdbc.support.KeyHolder; +import org.springframework.stereotype.Repository; +import roomescape.domain.ReservationTime; +import roomescape.dto.ReservationTimeRequest; + +@Repository +public class JdbcTemplateReservationTimeRepository implements ReservationTimeRepository { + private final JdbcTemplate jdbcTemplate; + + public JdbcTemplateReservationTimeRepository(JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } + + @Override + public ReservationTime save(ReservationTimeRequest reservationTimeRequest) { + KeyHolder keyHolder = new GeneratedKeyHolder(); + save(reservationTimeRequest, keyHolder); + return new ReservationTime(keyHolder.getKey().longValue(), reservationTimeRequest.startAt()); + } + + private void save(ReservationTimeRequest reservationTimeRequest, KeyHolder keyHolder) { + jdbcTemplate.update(con -> { + PreparedStatement pstmt = con.prepareStatement("insert into reservation_time(start_at) values ( ? )", + new String[]{"id"}); + pstmt.setTime(1, Time.valueOf(reservationTimeRequest.startAt())); + return pstmt; + }, keyHolder); + } + + @Override + public List findAll() { + return jdbcTemplate.query("select * from reservation_time", (rs, rowNum) -> { + long id = rs.getLong(1); + LocalTime time = rs.getTime(2).toLocalTime(); + return new ReservationTime(id, time); + }); + } + + @Override + public void delete(long id) { + jdbcTemplate.update("delete from reservation_time where id = ?", id); + } +} diff --git a/src/main/java/roomescape/repository/ReservationRepository.java b/src/main/java/roomescape/repository/ReservationRepository.java new file mode 100644 index 000000000..79c62ca32 --- /dev/null +++ b/src/main/java/roomescape/repository/ReservationRepository.java @@ -0,0 +1,13 @@ +package roomescape.repository; + +import java.util.List; +import roomescape.domain.Reservation; +import roomescape.dto.ReservationRequest; + +public interface ReservationRepository { + Reservation save(ReservationRequest reservationRequest); + + List findAll(); + + void delete(long id); +} diff --git a/src/main/java/roomescape/repository/ReservationTimeRepository.java b/src/main/java/roomescape/repository/ReservationTimeRepository.java new file mode 100644 index 000000000..5f6e144ee --- /dev/null +++ b/src/main/java/roomescape/repository/ReservationTimeRepository.java @@ -0,0 +1,13 @@ +package roomescape.repository; + +import java.util.List; +import roomescape.domain.ReservationTime; +import roomescape.dto.ReservationTimeRequest; + +public interface ReservationTimeRepository { + ReservationTime save(ReservationTimeRequest reservationTimeRequest); + + List findAll(); + + void delete(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 000000000..de6d8d528 --- /dev/null +++ b/src/main/java/roomescape/service/ReservationService.java @@ -0,0 +1,42 @@ +package roomescape.service; + +import java.util.List; +import org.springframework.stereotype.Service; +import roomescape.domain.Reservation; +import roomescape.domain.ReservationTime; +import roomescape.dto.ReservationRequest; +import roomescape.dto.ReservationResponse; +import roomescape.dto.ReservationTimeResponse; +import roomescape.repository.ReservationRepository; + +@Service +public class ReservationService { + private final ReservationRepository reservationRepository; + + public ReservationService(ReservationRepository reservationRepository) { + this.reservationRepository = reservationRepository; + } + + public ReservationResponse save(ReservationRequest reservationRequest) { + Reservation saved = reservationRepository.save(reservationRequest); + return toResponse(saved); + } + + private ReservationResponse toResponse(Reservation reservation) { + ReservationTime reservationTime = reservation.getReservationTime(); + ReservationTimeResponse reservationTimeResponse = new ReservationTimeResponse(reservationTime.getId(), + reservation.getTime()); + return new ReservationResponse(reservation.getId(), + reservation.getName(), reservation.getDate(), reservationTimeResponse); + } + + public List findAll() { + return reservationRepository.findAll().stream() + .map(this::toResponse) + .toList(); + } + + public void delete(long id) { + reservationRepository.delete(id); + } +} diff --git a/src/main/java/roomescape/service/ReservationTimeService.java b/src/main/java/roomescape/service/ReservationTimeService.java new file mode 100644 index 000000000..908a747d0 --- /dev/null +++ b/src/main/java/roomescape/service/ReservationTimeService.java @@ -0,0 +1,36 @@ +package roomescape.service; + +import java.util.List; +import org.springframework.stereotype.Service; +import roomescape.domain.ReservationTime; +import roomescape.dto.ReservationTimeRequest; +import roomescape.dto.ReservationTimeResponse; +import roomescape.repository.ReservationTimeRepository; + +@Service +public class ReservationTimeService { + private final ReservationTimeRepository reservationTimeRepository; + + public ReservationTimeService(ReservationTimeRepository reservationTimeRepository) { + this.reservationTimeRepository = reservationTimeRepository; + } + + public ReservationTimeResponse save(ReservationTimeRequest reservationTimeRequest) { + ReservationTime saved = reservationTimeRepository.save(reservationTimeRequest); + return toResponse(saved); + } + + private ReservationTimeResponse toResponse(ReservationTime saved) { + return new ReservationTimeResponse(saved.getId(), saved.getStartAt()); + } + + public List findAll() { + return reservationTimeRepository.findAll().stream() + .map(this::toResponse) + .toList(); + } + + public void delete(long id) { + reservationTimeRepository.delete(id); + } +} diff --git a/src/main/java/roomescape/storage/ReservationStorage.java b/src/main/java/roomescape/storage/ReservationStorage.java deleted file mode 100644 index 0fcf14be6..000000000 --- a/src/main/java/roomescape/storage/ReservationStorage.java +++ /dev/null @@ -1,59 +0,0 @@ -package roomescape.storage; - -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.atomic.AtomicLong; -import org.springframework.stereotype.Component; -import roomescape.domain.Reservation; -import roomescape.dto.ReservationRequest; - -@Component -public class ReservationStorage { - private final List reservations; - private final AtomicLong atomicLong; - - public ReservationStorage() { - this(new ArrayList<>()); - } - - public ReservationStorage(List reservations) { - this(reservations, new AtomicLong(0)); - } - - public ReservationStorage(List reservations, AtomicLong atomicLong) { - this.reservations = reservations; - this.atomicLong = atomicLong; - } - - public Reservation save(ReservationRequest reservationRequest) { - Reservation reservation = fromRequest(reservationRequest); - reservations.add(reservation); - return reservation; - } - - private Reservation fromRequest(ReservationRequest reservationRequest) { - long id = atomicLong.incrementAndGet(); - - String name = reservationRequest.name(); - LocalDate date = reservationRequest.date(); - LocalTime time = reservationRequest.time(); - LocalDateTime dateTime = LocalDateTime.of(date, time); - return new Reservation(id, name, dateTime); - } - - public List findAllReservations() { - return reservations.stream() - .sorted() - .toList(); - } - - public void delete(long reservationId) { - reservations.stream() - .filter(reservation -> reservation.hasSameId(reservationId)) - .findAny() - .ifPresent(reservations::remove); - } -} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index e69de29bb..63c01678a 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:product diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql new file mode 100644 index 000000000..44a68814d --- /dev/null +++ b/src/main/resources/schema.sql @@ -0,0 +1,16 @@ +CREATE TABLE IF NOT EXISTS reservation_time +( + id BIGINT NOT NULL AUTO_INCREMENT, + start_at VARCHAR(255) NOT NULL, + PRIMARY KEY (id) +); + +CREATE TABLE IF NOT EXISTS reservation +( + id BIGINT NOT NULL AUTO_INCREMENT, + name VARCHAR(255) NOT NULL, + date VARCHAR(255) NOT NULL, + time_id BIGINT NOT NULL, -- 컬럼 수정 + PRIMARY KEY (id), + FOREIGN KEY (time_id) REFERENCES reservation_time (id) -- 외래키 추가 +); diff --git a/src/main/resources/templates/admin/time.html b/src/main/resources/templates/admin/time.html index b8449b312..df450d6fc 100644 --- a/src/main/resources/templates/admin/time.html +++ b/src/main/resources/templates/admin/time.html @@ -15,17 +15,17 @@ LOGO diff --git a/src/test/java/roomescape/config/TestConfig.java b/src/test/java/roomescape/config/TestConfig.java deleted file mode 100644 index 1f3919c85..000000000 --- a/src/test/java/roomescape/config/TestConfig.java +++ /dev/null @@ -1,27 +0,0 @@ -package roomescape.config; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.atomic.AtomicLong; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import roomescape.domain.Reservation; -import roomescape.storage.ReservationStorage; - -@Configuration -public class TestConfig { - @Bean - ReservationStorage reservationStorage() { - return new ReservationStorage(reservations(), atomicLong()); - } - - @Bean - List reservations() { - return new ArrayList<>(); - } - - @Bean - AtomicLong atomicLong() { - return new AtomicLong(0); - } -} diff --git a/src/test/java/roomescape/controller/AdminControllerTest.java b/src/test/java/roomescape/controller/AdminControllerTest.java index 8ec1965ca..832a31fc0 100644 --- a/src/test/java/roomescape/controller/AdminControllerTest.java +++ b/src/test/java/roomescape/controller/AdminControllerTest.java @@ -20,6 +20,15 @@ void reservationPage() { AdminController adminController = new AdminController(); String reservationPage = adminController.reservationPage(); Assertions.assertThat(reservationPage) - .isEqualTo("admin/reservation-legacy"); + .isEqualTo("admin/reservation"); + } + + @Test + @DisplayName("시간 관리 페이지 경로를 정해진 경로로 매핑한다.") + void reservationTimePage() { + AdminController adminController = new AdminController(); + String reservationTimePage = adminController.reservationTimePage(); + Assertions.assertThat(reservationTimePage) + .isEqualTo("admin/time"); } } diff --git a/src/test/java/roomescape/controller/ReservationControllerTest.java b/src/test/java/roomescape/controller/ReservationControllerTest.java index 43365c8f7..5f301b199 100644 --- a/src/test/java/roomescape/controller/ReservationControllerTest.java +++ b/src/test/java/roomescape/controller/ReservationControllerTest.java @@ -1,7 +1,7 @@ package roomescape.controller; +import java.lang.reflect.Field; import java.time.LocalDate; -import java.time.LocalDateTime; import java.time.LocalTime; import java.util.ArrayList; import java.util.List; @@ -10,24 +10,36 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import roomescape.domain.Reservation; +import roomescape.domain.ReservationTime; import roomescape.dto.ReservationRequest; import roomescape.dto.ReservationResponse; -import roomescape.storage.ReservationStorage; +import roomescape.dto.ReservationTimeResponse; +import roomescape.repository.CollectionReservationRepository; +import roomescape.repository.CollectionReservationTimeRepository; +import roomescape.service.ReservationService; class ReservationControllerTest { + static final long timeId = 1L; + static final LocalTime time = LocalTime.now(); + private final CollectionReservationTimeRepository timeRepository = new CollectionReservationTimeRepository( + new ArrayList<>(List.of(new ReservationTime(timeId, time))) + ); + @Test @DisplayName("예약 정보를 잘 저장하는지 확인한다.") void saveReservation() { - ReservationStorage reservationStorage = new ReservationStorage(); - ReservationController reservationController = new ReservationController(reservationStorage); + CollectionReservationRepository collectionReservationRepository = new CollectionReservationRepository( + timeRepository); + ReservationService reservationService = new ReservationService(collectionReservationRepository); + ReservationController reservationController = new ReservationController(reservationService); LocalDate date = LocalDate.now(); - LocalTime time = LocalTime.now(); ReservationResponse saveResponse = reservationController.saveReservation( - new ReservationRequest(date, "폴라", time)); + new ReservationRequest(date, "폴라", timeId)); long id = Objects.requireNonNull(saveResponse).id(); - ReservationResponse expected = new ReservationResponse(id, "폴라", date, time); + ReservationResponse expected = new ReservationResponse(id, "폴라", date, + new ReservationTimeResponse(timeId, time)); Assertions.assertThat(saveResponse) .isEqualTo(expected); @@ -36,8 +48,10 @@ void saveReservation() { @Test @DisplayName("예약 정보를 잘 불러오는지 확인한다.") void findAllReservations() { - ReservationStorage reservationStorage = new ReservationStorage(); - ReservationController reservationController = new ReservationController(reservationStorage); + CollectionReservationRepository collectionReservationRepository = new CollectionReservationRepository( + timeRepository); + ReservationService reservationService = new ReservationService(collectionReservationRepository); + ReservationController reservationController = new ReservationController(reservationService); List allReservations = reservationController.findAllReservations(); Assertions.assertThat(allReservations) @@ -47,9 +61,12 @@ void findAllReservations() { @Test @DisplayName("예약 정보를 잘 지우는지 확인한다.") void delete() { - List reservations = List.of(new Reservation(1, "폴라", LocalDateTime.now())); - ReservationStorage reservationStorage = new ReservationStorage(new ArrayList<>(reservations)); - ReservationController reservationController = new ReservationController(reservationStorage); + List reservations = List.of( + new Reservation(1L, "폴라", LocalDate.now(), new ReservationTime(LocalTime.now()))); + CollectionReservationRepository collectionReservationRepository = new CollectionReservationRepository( + new ArrayList<>(reservations), timeRepository); + ReservationService reservationService = new ReservationService(collectionReservationRepository); + ReservationController reservationController = new ReservationController(reservationService); reservationController.delete(1L); List reservationResponses = reservationController.findAllReservations(); @@ -57,4 +74,24 @@ void delete() { Assertions.assertThat(reservationResponses) .isEmpty(); } + + @Test + @DisplayName("내부에 Repository를 의존하고 있지 않은지 확인한다.") + void checkRepositoryDependency() { + CollectionReservationRepository collectionReservationRepository = new CollectionReservationRepository( + timeRepository); + ReservationService reservationService = new ReservationService(collectionReservationRepository); + ReservationController reservationController = new ReservationController(reservationService); + + boolean isRepositoryInjected = false; + + for (Field field : reservationController.getClass().getDeclaredFields()) { + if (field.getType().getName().contains("Repository")) { + isRepositoryInjected = true; + break; + } + } + + Assertions.assertThat(isRepositoryInjected).isFalse(); + } } diff --git a/src/test/java/roomescape/controller/ReservationTimeControllerTest.java b/src/test/java/roomescape/controller/ReservationTimeControllerTest.java new file mode 100644 index 000000000..84ad5b27a --- /dev/null +++ b/src/test/java/roomescape/controller/ReservationTimeControllerTest.java @@ -0,0 +1,78 @@ +package roomescape.controller; + +import java.lang.reflect.Field; +import java.time.LocalTime; +import java.util.ArrayList; +import java.util.List; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import roomescape.domain.ReservationTime; +import roomescape.dto.ReservationTimeRequest; +import roomescape.dto.ReservationTimeResponse; +import roomescape.repository.CollectionReservationTimeRepository; +import roomescape.service.ReservationTimeService; + +class ReservationTimeControllerTest { + @Test + @DisplayName("시간을 잘 저장하는지 확인한다.") + void save() { + CollectionReservationTimeRepository reservationTimeRepository = new CollectionReservationTimeRepository(); + ReservationTimeService reservationTimeService = new ReservationTimeService(reservationTimeRepository); + ReservationTimeController reservationTimeController = new ReservationTimeController(reservationTimeService); + LocalTime time = LocalTime.now(); + + ReservationTimeResponse save = reservationTimeController.save(new ReservationTimeRequest(time)); + + ReservationTimeResponse expected = new ReservationTimeResponse(save.id(), time); + Assertions.assertThat(save) + .isEqualTo(expected); + } + + @Test + @DisplayName("시간을 잘 불러오는지 확인한다.") + void findAll() { + CollectionReservationTimeRepository reservationTimeRepository = new CollectionReservationTimeRepository(); + ReservationTimeService reservationTimeService = new ReservationTimeService(reservationTimeRepository); + ReservationTimeController reservationTimeController = new ReservationTimeController(reservationTimeService); + List reservationTimeResponses = reservationTimeController.findAll(); + + Assertions.assertThat(reservationTimeResponses) + .isEmpty(); + } + + @Test + @DisplayName("시간을 잘 지우는지 확인한다.") + void delete() { + CollectionReservationTimeRepository reservationTimeRepository = new CollectionReservationTimeRepository( + new ArrayList<>(List.of(new ReservationTime(1L, LocalTime.now()))) + ); + ReservationTimeService reservationTimeService = new ReservationTimeService(reservationTimeRepository); + ReservationTimeController reservationTimeController = new ReservationTimeController(reservationTimeService); + + reservationTimeController.delete(1); + + List reservationTimeResponses = reservationTimeController.findAll(); + Assertions.assertThat(reservationTimeResponses) + .isEmpty(); + } + + @Test + @DisplayName("내부에 Repository를 의존하고 있지 않은지 확인한다.") + void checkRepositoryDependency() { + CollectionReservationTimeRepository reservationTimeRepository = new CollectionReservationTimeRepository(); + ReservationTimeService reservationTimeService = new ReservationTimeService(reservationTimeRepository); + ReservationTimeController reservationTimeController = new ReservationTimeController(reservationTimeService); + + boolean isRepositoryInjected = false; + + for (Field field : reservationTimeController.getClass().getDeclaredFields()) { + if (field.getType().getName().contains("Repository")) { + isRepositoryInjected = true; + break; + } + } + + Assertions.assertThat(isRepositoryInjected).isFalse(); + } +} diff --git a/src/test/java/roomescape/domain/ReservationTest.java b/src/test/java/roomescape/domain/ReservationTest.java index 9aae6fcc9..63bc68909 100644 --- a/src/test/java/roomescape/domain/ReservationTest.java +++ b/src/test/java/roomescape/domain/ReservationTest.java @@ -1,6 +1,7 @@ package roomescape.domain; -import java.time.LocalDateTime; +import java.time.LocalDate; +import java.time.LocalTime; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -9,8 +10,10 @@ class ReservationTest { @Test @DisplayName("날짜를 기준으로 비교를 잘 하는지 확인.") void compareTo() { - Reservation first = new Reservation(1L, "폴라", LocalDateTime.of(1999, 12, 1, 16, 30)); - Reservation second = new Reservation(2L, "로빈", LocalDateTime.of(1998, 1, 8, 10, 30)); + Reservation first = new Reservation(1L, "폴라", LocalDate.of(1999, 12, 1), new ReservationTime( + LocalTime.of(16, 30))); + Reservation second = new Reservation(2L, "로빈", LocalDate.of(1998, 1, 8), new ReservationTime( + LocalTime.of(16, 30))); int compareTo = first.compareTo(second); Assertions.assertThat(compareTo) .isGreaterThan(0); diff --git a/src/test/java/roomescape/infra/DBConnectionTest.java b/src/test/java/roomescape/infra/DBConnectionTest.java new file mode 100644 index 000000000..8f856916a --- /dev/null +++ b/src/test/java/roomescape/infra/DBConnectionTest.java @@ -0,0 +1,36 @@ +package roomescape.infra; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; + +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; + +@SpringBootTest +public class DBConnectionTest { + @Autowired + private JdbcTemplate jdbcTemplate; + + @Test + @DisplayName("데이터베이스 접속이 잘 되는지 확인.") + void connectToDB() { + try (Connection connection = jdbcTemplate.getDataSource().getConnection()) { + assertConnection(connection); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + + private void assertConnection(Connection connection) { + assertAll( + () -> assertThat(connection).isNotNull(), + () -> assertThat(connection.getCatalog()).isEqualTo("TEST"), + () -> assertThat(connection.getMetaData().getTables(null, null, "RESERVATION", null).next()).isTrue() + ); + } +} diff --git a/src/test/java/roomescape/integration/AdminIntegrationTest.java b/src/test/java/roomescape/integration/AdminIntegrationTest.java index 14f40d96d..068b0dbe2 100644 --- a/src/test/java/roomescape/integration/AdminIntegrationTest.java +++ b/src/test/java/roomescape/integration/AdminIntegrationTest.java @@ -5,27 +5,32 @@ import io.restassured.RestAssured; import io.restassured.http.ContentType; import java.util.HashMap; -import java.util.List; import java.util.Map; -import java.util.concurrent.atomic.AtomicLong; +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 roomescape.domain.Reservation; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.boot.test.web.server.LocalServerPort; +import org.springframework.jdbc.core.JdbcTemplate; -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) +@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) public class AdminIntegrationTest { + @LocalServerPort + private int port; @Autowired - private List reservations; - @Autowired - private AtomicLong atomicLong; + private JdbcTemplate jdbcTemplate; @BeforeEach void init() { - reservations.clear(); - atomicLong.set(0); + jdbcTemplate.update("delete from reservation"); + jdbcTemplate.update("ALTER TABLE reservation alter column id restart with 1"); + jdbcTemplate.update("delete from reservation_time"); + jdbcTemplate.update("ALTER TABLE reservation_time alter column id restart with 1"); + jdbcTemplate.update("insert into reservation_time(start_at) values('11:56')"); + RestAssured.port = port; } @Test @@ -55,10 +60,13 @@ void adminReservationPageLoad() { @Test @DisplayName("관리자 예약 페이지가 잘 동작한다.") void adminReservationPageWork() { - Map params = new HashMap<>(); + Integer integer = jdbcTemplate.queryForObject("select id from reservation_time", + Integer.class); + System.out.println(integer); + Map params = new HashMap<>(); params.put("name", "브라운"); params.put("date", "2023-08-05"); - params.put("time", "15:40"); + params.put("timeId", 1); RestAssured.given().log().all() .contentType(ContentType.JSON) @@ -85,4 +93,56 @@ void adminReservationPageWork() { .statusCode(200) .body("size()", is(0)); } + + @Test + @DisplayName("관리자 예약 페이지가 DB와 함께 잘 동작한다.") + void adminReservationPageWorkWithDB() { + Map params = new HashMap<>(); + params.put("name", "브라운"); + params.put("date", "2023-08-05"); + params.put("timeId", 1); + + RestAssured.given().log().all() + .contentType(ContentType.JSON) + .body(params) + .when().post("/reservations") + .then().log().all() + .statusCode(200); + + Integer count = jdbcTemplate.queryForObject("SELECT count(1) from reservation", Integer.class); + Assertions.assertThat(count).isEqualTo(1); + + RestAssured.given().log().all() + .when().delete("/reservations/1") + .then().log().all() + .statusCode(200); + + Integer countAfterDelete = jdbcTemplate.queryForObject("SELECT count(1) from reservation", Integer.class); + Assertions.assertThat(countAfterDelete).isEqualTo(0); + } + + @Test + @DisplayName("시간 관리 페이지가 잘 동작한다.") + void reservationTimePageWork() { + Map params = new HashMap<>(); + params.put("startAt", "10:00"); + + RestAssured.given().log().all() + .contentType(ContentType.JSON) + .body(params) + .when().post("/times") + .then().log().all() + .statusCode(200); + + RestAssured.given().log().all() + .when().get("/times") + .then().log().all() + .statusCode(200) + .body("size()", is(2)); + + RestAssured.given().log().all() + .when().delete("/times/2") + .then().log().all() + .statusCode(200); + } } diff --git a/src/test/java/roomescape/repository/CollectionReservationRepository.java b/src/test/java/roomescape/repository/CollectionReservationRepository.java new file mode 100644 index 000000000..087cc9de0 --- /dev/null +++ b/src/test/java/roomescape/repository/CollectionReservationRepository.java @@ -0,0 +1,70 @@ +package roomescape.repository; + +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicLong; +import java.util.function.Predicate; +import roomescape.domain.Reservation; +import roomescape.domain.ReservationTime; +import roomescape.dto.ReservationRequest; + +public class CollectionReservationRepository implements ReservationRepository { + private final List reservations; + private final AtomicLong atomicLong; + private final CollectionReservationTimeRepository timeRepository; + + public CollectionReservationRepository(CollectionReservationTimeRepository timeRepository) { + this(new ArrayList<>(), new AtomicLong(0), timeRepository); + } + + public CollectionReservationRepository(List reservations, AtomicLong atomicLong, + CollectionReservationTimeRepository timeRepository) { + this.reservations = reservations; + this.atomicLong = atomicLong; + this.timeRepository = timeRepository; + } + + public CollectionReservationRepository(List reservations, + CollectionReservationTimeRepository timeRepository) { + this(reservations, new AtomicLong(0), timeRepository); + } + + @Override + public Reservation save(ReservationRequest reservationRequest) { + Reservation reservation = fromRequest(reservationRequest); + reservations.add(reservation); + return reservation; + } + + private Reservation fromRequest(ReservationRequest reservationRequest) { + long id = atomicLong.incrementAndGet(); + + String name = reservationRequest.name(); + LocalDate date = reservationRequest.date(); + ReservationTime reservationTime = timeRepository.findAll().stream() + .filter(sameId(reservationRequest)) + .findAny() + .orElseThrow(); + return new Reservation(id, name, date, reservationTime); + } + + private static Predicate sameId(ReservationRequest reservationRequest) { + return reservationTime -> reservationTime.getId() == reservationRequest.timeId(); + } + + @Override + public List findAll() { + return reservations.stream() + .sorted() + .toList(); + } + + @Override + public void delete(long id) { + reservations.stream() + .filter(reservation -> reservation.hasSameId(id)) + .findAny() + .ifPresent(reservations::remove); + } +} diff --git a/src/test/java/roomescape/repository/CollectionReservationTimeRepository.java b/src/test/java/roomescape/repository/CollectionReservationTimeRepository.java new file mode 100644 index 000000000..b6f22fe98 --- /dev/null +++ b/src/test/java/roomescape/repository/CollectionReservationTimeRepository.java @@ -0,0 +1,46 @@ +package roomescape.repository; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicLong; +import roomescape.domain.ReservationTime; +import roomescape.dto.ReservationTimeRequest; + +public class CollectionReservationTimeRepository implements ReservationTimeRepository { + private final List reservationTimes; + private final AtomicLong atomicLong; + + public CollectionReservationTimeRepository() { + this(new ArrayList<>()); + } + + public CollectionReservationTimeRepository(List reservationTimes) { + this(reservationTimes, new AtomicLong(0)); + } + + public CollectionReservationTimeRepository(List reservationTimes, AtomicLong atomicLong) { + this.reservationTimes = reservationTimes; + this.atomicLong = atomicLong; + } + + @Override + public ReservationTime save(ReservationTimeRequest reservationTimeRequest) { + ReservationTime reservationTime = new ReservationTime(atomicLong.incrementAndGet(), + reservationTimeRequest.startAt()); + reservationTimes.add(reservationTime); + return reservationTime; + } + + @Override + public List findAll() { + return List.copyOf(reservationTimes); + } + + @Override + public void delete(long id) { + reservationTimes.stream() + .filter(reservationTime -> reservationTime.getId().equals(id)) + .findAny() + .ifPresent(reservationTimes::remove); + } +} diff --git a/src/test/java/roomescape/repository/JdbcTemplateReservationRepositoryTest.java b/src/test/java/roomescape/repository/JdbcTemplateReservationRepositoryTest.java new file mode 100644 index 000000000..c2acc8994 --- /dev/null +++ b/src/test/java/roomescape/repository/JdbcTemplateReservationRepositoryTest.java @@ -0,0 +1,68 @@ +package roomescape.repository; + +import java.time.LocalDate; +import java.util.List; +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 roomescape.domain.Reservation; +import roomescape.dto.ReservationRequest; + +@SpringBootTest +class JdbcTemplateReservationRepositoryTest { + @Autowired + private ReservationRepository reservationRepository; + @Autowired + private JdbcTemplate jdbcTemplate; + + @BeforeEach + void init() { + jdbcTemplate.update("delete from reservation"); + jdbcTemplate.update("ALTER TABLE reservation alter column id restart with 1"); + jdbcTemplate.update("delete from reservation_time"); + jdbcTemplate.update("ALTER TABLE reservation_time alter column id restart with 1"); + jdbcTemplate.update("insert into reservation_time(start_at) values('11:56')"); + } + + @Test + @DisplayName("Reservation 을 잘 저장하는지 확인한다.") + void save() { + var beforeSave = reservationRepository.findAll(); + Reservation saved = reservationRepository.save(new ReservationRequest(LocalDate.now(), "test", 1)); + var afterSave = reservationRepository.findAll(); + + Assertions.assertThat(afterSave) + .containsAll(beforeSave) + .contains(saved); + } + + @Test + @DisplayName("Reservation 을 잘 조회하는지 확인한다.") + void findAll() { + List beforeSave = reservationRepository.findAll(); + reservationRepository.save(new ReservationRequest(LocalDate.now(), "test", 1)); + reservationRepository.save(new ReservationRequest(LocalDate.now(), "test2", 1)); + + List afterSave = reservationRepository.findAll(); + Assertions.assertThat(afterSave.size()) + .isEqualTo(beforeSave.size() + 2); + } + + @Test + @DisplayName("Reservation 을 잘 지우는지 확인한다.") + void delete() { + List beforeSaveAndDelete = reservationRepository.findAll(); + reservationRepository.save(new ReservationRequest(LocalDate.now(), "test", 1)); + + reservationRepository.delete(1L); + + List afterSaveAndDelete = reservationRepository.findAll(); + + Assertions.assertThat(beforeSaveAndDelete) + .containsExactlyElementsOf(afterSaveAndDelete); + } +} diff --git a/src/test/java/roomescape/repository/JdbcTemplateReservationTimeRepositoryTest.java b/src/test/java/roomescape/repository/JdbcTemplateReservationTimeRepositoryTest.java new file mode 100644 index 000000000..5bc5cd67f --- /dev/null +++ b/src/test/java/roomescape/repository/JdbcTemplateReservationTimeRepositoryTest.java @@ -0,0 +1,68 @@ +package roomescape.repository; + +import java.time.LocalTime; +import java.util.List; +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 roomescape.domain.ReservationTime; +import roomescape.dto.ReservationTimeRequest; + +@SpringBootTest +class JdbcTemplateReservationTimeRepositoryTest { + @Autowired + private ReservationTimeRepository reservationTimeRepository; + @Autowired + private JdbcTemplate jdbcTemplate; + + @BeforeEach + void init() { + jdbcTemplate.update("delete from reservation"); + jdbcTemplate.update("ALTER TABLE reservation alter column id restart with 1"); + jdbcTemplate.update("delete from reservation_time"); + jdbcTemplate.update("ALTER TABLE reservation_time alter column id restart with 1"); + } + + @Test + @DisplayName("ReservationTime 을 잘 저장하는지 확인한다.") + void save() { + var beforeSave = reservationTimeRepository.findAll().stream().map(ReservationTime::getId).toList(); + ReservationTime saved = reservationTimeRepository.save(new ReservationTimeRequest(LocalTime.now())); + var afterSave = reservationTimeRepository.findAll().stream().map(ReservationTime::getId).toList(); + + Assertions.assertThat(afterSave) + .containsAll(beforeSave) + .contains(saved.getId()); + } + + @Test + @DisplayName("ReservationTime 을 잘 조회하는지 확인한다.") + void findAll() { + List beforeSave = reservationTimeRepository.findAll(); + reservationTimeRepository.save(new ReservationTimeRequest(LocalTime.now())); + reservationTimeRepository.save(new ReservationTimeRequest(LocalTime.now())); + + List afterSave = reservationTimeRepository.findAll(); + + Assertions.assertThat(afterSave.size()) + .isEqualTo(beforeSave.size() + 2); + } + + @Test + @DisplayName("ReservationTime 을 잘 지우하는지 확인한다.") + void delete() { + List beforeSaveAndDelete = reservationTimeRepository.findAll(); + reservationTimeRepository.save(new ReservationTimeRequest(LocalTime.now())); + + reservationTimeRepository.delete(1L); + + List afterSaveAndDelete = reservationTimeRepository.findAll(); + + Assertions.assertThat(beforeSaveAndDelete) + .containsExactlyInAnyOrderElementsOf(afterSaveAndDelete); + } +} diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties new file mode 100644 index 000000000..b53e73970 --- /dev/null +++ b/src/test/resources/application.properties @@ -0,0 +1,2 @@ +spring.h2.console.enabled=true +spring.datasource.url=jdbc:h2:mem:test diff --git a/src/test/resources/schema.sql b/src/test/resources/schema.sql new file mode 100644 index 000000000..0945a159b --- /dev/null +++ b/src/test/resources/schema.sql @@ -0,0 +1,16 @@ +CREATE TABLE IF NOT EXISTS reservation_time +( + id BIGINT NOT NULL AUTO_INCREMENT, + start_at VARCHAR(255) NOT NULL, + PRIMARY KEY (id) +); + +CREATE TABLE IF NOT EXISTS 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) -- 외래키 추가 +);