generated from pricelees/issue-pr-template
test: ReservationService 테스트 코틀린 전환
This commit is contained in:
parent
c2d4e10160
commit
2b234511ac
@ -1,239 +0,0 @@
|
||||
package roomescape.reservation.business;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.context.jdbc.Sql;
|
||||
import org.springframework.test.context.jdbc.Sql.ExecutionPhase;
|
||||
|
||||
import roomescape.common.exception.RoomescapeException;
|
||||
import roomescape.member.business.MemberService;
|
||||
import roomescape.member.infrastructure.persistence.MemberEntity;
|
||||
import roomescape.member.infrastructure.persistence.MemberRepository;
|
||||
import roomescape.member.infrastructure.persistence.Role;
|
||||
import roomescape.reservation.infrastructure.persistence.ReservationEntity;
|
||||
import roomescape.reservation.infrastructure.persistence.ReservationRepository;
|
||||
import roomescape.reservation.infrastructure.persistence.ReservationStatus;
|
||||
import roomescape.reservation.infrastructure.persistence.ReservationTimeEntity;
|
||||
import roomescape.reservation.infrastructure.persistence.ReservationTimeRepository;
|
||||
import roomescape.reservation.web.ReservationRequest;
|
||||
import roomescape.reservation.web.ReservationResponse;
|
||||
import roomescape.reservation.web.WaitingRequest;
|
||||
import roomescape.theme.business.ThemeService;
|
||||
import roomescape.theme.infrastructure.persistence.ThemeEntity;
|
||||
import roomescape.theme.infrastructure.persistence.ThemeRepository;
|
||||
|
||||
@SpringBootTest
|
||||
@Sql(scripts = "/truncate.sql", executionPhase = ExecutionPhase.BEFORE_TEST_METHOD)
|
||||
@Import({ReservationService.class, MemberService.class, ReservationTimeService.class, ThemeService.class})
|
||||
class ReservationServiceTest {
|
||||
|
||||
@Autowired
|
||||
ReservationTimeRepository reservationTimeRepository;
|
||||
@Autowired
|
||||
ReservationRepository reservationRepository;
|
||||
@Autowired
|
||||
ThemeRepository themeRepository;
|
||||
@Autowired
|
||||
MemberRepository memberRepository;
|
||||
@Autowired
|
||||
private ReservationService reservationService;
|
||||
|
||||
@Test
|
||||
@DisplayName("예약을 추가할때 이미 예약이 존재하면 예외가 발생한다.")
|
||||
void reservationAlreadyExistFail() {
|
||||
// given
|
||||
ReservationTimeEntity reservationTime = reservationTimeRepository.save(
|
||||
new ReservationTimeEntity(null, LocalTime.of(12, 30)));
|
||||
ThemeEntity theme = themeRepository.save(new ThemeEntity(null, "테마명", "설명", "썸네일URL"));
|
||||
MemberEntity member1 = memberRepository.save(
|
||||
new MemberEntity(null, "name", "email@email.com", "password", Role.MEMBER));
|
||||
MemberEntity member2 = memberRepository.save(
|
||||
new MemberEntity(null, "name2", "email2@email.com", "password", Role.MEMBER));
|
||||
LocalDate date = LocalDate.now().plusDays(1L);
|
||||
|
||||
// when
|
||||
reservationService.addReservation(
|
||||
new ReservationRequest(date, reservationTime.getId(), theme.getId(), "paymentKey", "orderId",
|
||||
1000L, "paymentType"), member2.getId());
|
||||
|
||||
// then
|
||||
assertThatThrownBy(() -> reservationService.addReservation(
|
||||
new ReservationRequest(date, reservationTime.getId(), theme.getId(), "paymentKey", "orderId",
|
||||
1000L, "paymentType"), member1.getId()))
|
||||
.isInstanceOf(RoomescapeException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("이미 예약한 멤버가 같은 테마에 대기를 신청하면 예외가 발생한다.")
|
||||
void requestWaitWhenAlreadyReserveFail() {
|
||||
// given
|
||||
ReservationTimeEntity reservationTime = reservationTimeRepository.save(
|
||||
new ReservationTimeEntity(null, LocalTime.of(12, 30)));
|
||||
ThemeEntity theme = themeRepository.save(new ThemeEntity(null, "테마명", "설명", "썸네일URL"));
|
||||
MemberEntity member = memberRepository.save(
|
||||
new MemberEntity(null, "name", "email@email.com", "password", Role.MEMBER));
|
||||
LocalDate date = LocalDate.now().plusDays(1L);
|
||||
|
||||
// when
|
||||
reservationService.addReservation(
|
||||
new ReservationRequest(date, reservationTime.getId(), theme.getId(), "paymentKey", "orderId",
|
||||
1000L, "paymentType"), member.getId());
|
||||
|
||||
// then
|
||||
assertThatThrownBy(() -> reservationService.addWaiting(
|
||||
new WaitingRequest(date, reservationTime.getId(), theme.getId()), member.getId()))
|
||||
.isInstanceOf(RoomescapeException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("예약 대기를 두 번 이상 요청하면 예외가 발생한다.")
|
||||
void requestWaitTwiceFail() {
|
||||
// given
|
||||
ReservationTimeEntity reservationTime = reservationTimeRepository.save(
|
||||
new ReservationTimeEntity(null, LocalTime.of(12, 30)));
|
||||
ThemeEntity theme = themeRepository.save(new ThemeEntity(null, "테마명", "설명", "썸네일URL"));
|
||||
MemberEntity member = memberRepository.save(
|
||||
new MemberEntity(null, "name", "email@email.com", "password", Role.MEMBER));
|
||||
MemberEntity member1 = memberRepository.save(
|
||||
new MemberEntity(null, "name1", "email1@email.com", "password", Role.MEMBER));
|
||||
LocalDate date = LocalDate.now().plusDays(1L);
|
||||
|
||||
// when
|
||||
reservationService.addReservation(
|
||||
new ReservationRequest(date, reservationTime.getId(), theme.getId(), "paymentKey", "orderId",
|
||||
1000L, "paymentType"), member.getId());
|
||||
|
||||
reservationService.addWaiting(
|
||||
new WaitingRequest(date, reservationTime.getId(), theme.getId()), member1.getId());
|
||||
|
||||
// then
|
||||
assertThatThrownBy(() -> reservationService.addWaiting(
|
||||
new WaitingRequest(date, reservationTime.getId(), theme.getId()), member1.getId()))
|
||||
.isInstanceOf(RoomescapeException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("이미 지난 날짜로 예약을 생성하면 예외가 발생한다.")
|
||||
void beforeDateReservationFail() {
|
||||
// given
|
||||
ReservationTimeEntity reservationTime = reservationTimeRepository.save(
|
||||
new ReservationTimeEntity(null, LocalTime.of(12, 30)));
|
||||
ThemeEntity theme = themeRepository.save(new ThemeEntity(null, "테마명", "설명", "썸네일URL"));
|
||||
MemberEntity member = memberRepository.save(
|
||||
new MemberEntity(null, "name", "email@email.com", "password", Role.MEMBER));
|
||||
LocalDate beforeDate = LocalDate.now().minusDays(1L);
|
||||
|
||||
// when & then
|
||||
assertThatThrownBy(() -> reservationService.addReservation(
|
||||
new ReservationRequest(beforeDate, reservationTime.getId(), theme.getId(), "paymentKey", "orderId",
|
||||
1000L, "paymentType"), member.getId()))
|
||||
.isInstanceOf(RoomescapeException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("현재 날짜가 예약 당일이지만, 이미 지난 시간으로 예약을 생성하면 예외가 발생한다.")
|
||||
void beforeTimeReservationFail() {
|
||||
// given
|
||||
LocalDateTime beforeTime = LocalDateTime.now().minusHours(1L).withNano(0);
|
||||
ReservationTimeEntity reservationTime = reservationTimeRepository.save(
|
||||
new ReservationTimeEntity(null, beforeTime.toLocalTime()));
|
||||
ThemeEntity theme = themeRepository.save(new ThemeEntity(null, "테마명", "설명", "썸네일URL"));
|
||||
MemberEntity member = memberRepository.save(
|
||||
new MemberEntity(null, "name", "email@email.com", "password", Role.MEMBER));
|
||||
|
||||
// when & then
|
||||
assertThatThrownBy(() -> reservationService.addReservation(
|
||||
new ReservationRequest(beforeTime.toLocalDate(), reservationTime.getId(), theme.getId(), "paymentKey",
|
||||
"orderId", 1000L, "paymentType"), member.getId()))
|
||||
.isInstanceOf(RoomescapeException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("존재하지 않는 회원이 예약을 생성하려고 하면 예외가 발생한다.")
|
||||
void notExistMemberReservationFail() {
|
||||
// given
|
||||
LocalDateTime beforeTime = LocalDateTime.now().minusDays(1L).withNano(0);
|
||||
ReservationTimeEntity reservationTime = reservationTimeRepository.save(
|
||||
new ReservationTimeEntity(null, beforeTime.toLocalTime()));
|
||||
ThemeEntity theme = themeRepository.save(new ThemeEntity(null, "테마명", "설명", "썸네일URL"));
|
||||
Long NotExistMemberId = 1L;
|
||||
|
||||
// when & then
|
||||
assertThatThrownBy(() -> reservationService.addReservation(
|
||||
new ReservationRequest(beforeTime.toLocalDate(), reservationTime.getId(), theme.getId(), "paymentKey",
|
||||
"orderId", 1000L, "paymentType"),
|
||||
NotExistMemberId))
|
||||
.isInstanceOf(RoomescapeException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("예약을 조회할 때 종료 날짜가 시작 날짜 이전이면 예외가 발생한다.")
|
||||
void invalidDateRange() {
|
||||
// given
|
||||
LocalDate dateFrom = LocalDate.now().plusDays(1);
|
||||
LocalDate dateTo = LocalDate.now();
|
||||
|
||||
// when & then
|
||||
assertThatThrownBy(() -> reservationService.findFilteredReservations(null, null, dateFrom, dateTo))
|
||||
.isInstanceOf(RoomescapeException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("대기중인 예약을 승인할 때, 기존에 예약이 존재하면 예외가 발생한다.")
|
||||
void confirmWaitingWhenReservationExist() {
|
||||
// given
|
||||
ReservationTimeEntity reservationTime = reservationTimeRepository.save(
|
||||
new ReservationTimeEntity(null, LocalTime.of(12, 30)));
|
||||
ThemeEntity theme = themeRepository.save(new ThemeEntity(null, "테마명", "설명", "썸네일URL"));
|
||||
MemberEntity admin = memberRepository.save(
|
||||
new MemberEntity(null, "admin", "admin@email.com", "password", Role.ADMIN));
|
||||
MemberEntity member = memberRepository.save(
|
||||
new MemberEntity(null, "name", "email@email.com", "password", Role.MEMBER));
|
||||
MemberEntity member1 = memberRepository.save(
|
||||
new MemberEntity(null, "name1", "email1@email.com", "password", Role.MEMBER));
|
||||
|
||||
reservationService.addReservation(
|
||||
new ReservationRequest(LocalDate.now().plusDays(1L), reservationTime.getId(), theme.getId(),
|
||||
"paymentKey", "orderId",
|
||||
1000L, "paymentType"), member.getId());
|
||||
ReservationResponse waiting = reservationService.addWaiting(
|
||||
new WaitingRequest(LocalDate.now().plusDays(1L), reservationTime.getId(), theme.getId()),
|
||||
member1.getId());
|
||||
|
||||
// when & then
|
||||
assertThatThrownBy(() -> reservationService.approveWaiting(waiting.id, admin.getId()))
|
||||
.isInstanceOf(RoomescapeException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("대기중인 예약을 확정한다.")
|
||||
void approveWaiting() {
|
||||
// given
|
||||
ReservationTimeEntity reservationTime = reservationTimeRepository.save(
|
||||
new ReservationTimeEntity(null, LocalTime.of(12, 30)));
|
||||
ThemeEntity theme = themeRepository.save(new ThemeEntity(null, "테마명", "설명", "썸네일URL"));
|
||||
MemberEntity admin = memberRepository.save(
|
||||
new MemberEntity(null, "admin", "admin@email.com", "password", Role.ADMIN));
|
||||
MemberEntity member = memberRepository.save(
|
||||
new MemberEntity(null, "name", "email@email.com", "password", Role.MEMBER));
|
||||
|
||||
// when
|
||||
ReservationResponse waiting = reservationService.addWaiting(
|
||||
new WaitingRequest(LocalDate.now().plusDays(1L), reservationTime.getId(), theme.getId()),
|
||||
member.getId());
|
||||
reservationService.approveWaiting(waiting.id, admin.getId());
|
||||
|
||||
// then
|
||||
ReservationEntity confirmed = reservationRepository.findById(waiting.id).get();
|
||||
assertThat(confirmed.getReservationStatus()).isEqualTo(ReservationStatus.CONFIRMED_PAYMENT_REQUIRED);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,175 @@
|
||||
package roomescape.reservation.business
|
||||
|
||||
import io.kotest.assertions.throwables.shouldThrow
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
import io.kotest.matchers.shouldBe
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import roomescape.common.exception.ErrorType
|
||||
import roomescape.common.exception.RoomescapeException
|
||||
import roomescape.member.business.MemberService
|
||||
import roomescape.member.infrastructure.persistence.Role
|
||||
import roomescape.reservation.infrastructure.persistence.ReservationRepository
|
||||
import roomescape.theme.business.ThemeService
|
||||
import roomescape.util.MemberFixture
|
||||
import roomescape.util.ReservationFixture
|
||||
import roomescape.util.ReservationTimeFixture
|
||||
import java.time.LocalDate
|
||||
import java.time.LocalTime
|
||||
|
||||
class ReservationServiteTest : FunSpec({
|
||||
|
||||
val reservationRepository: ReservationRepository = mockk()
|
||||
val reservationTimeService: ReservationTimeService = mockk()
|
||||
val memberService: MemberService = mockk()
|
||||
val themeService: ThemeService = mockk()
|
||||
val reservationService = ReservationService(
|
||||
reservationRepository,
|
||||
reservationTimeService,
|
||||
memberService,
|
||||
themeService
|
||||
)
|
||||
|
||||
context("예약을 추가할 때") {
|
||||
test("이미 예약이 있으면 예외를 던진다.") {
|
||||
every {
|
||||
reservationRepository.exists(any())
|
||||
} returns true
|
||||
|
||||
val reservationRequest = ReservationFixture.createRequest()
|
||||
|
||||
shouldThrow<RoomescapeException> {
|
||||
reservationService.addReservation(reservationRequest, 1L)
|
||||
}.also {
|
||||
it.errorType shouldBe ErrorType.RESERVATION_DUPLICATED
|
||||
}
|
||||
}
|
||||
|
||||
context("날짜, 시간이 잘못 입력되면 예외를 던진다.") {
|
||||
every {
|
||||
reservationRepository.exists(any())
|
||||
} returns false
|
||||
|
||||
every {
|
||||
themeService.findThemeById(any())
|
||||
} returns mockk()
|
||||
|
||||
every {
|
||||
memberService.findById(any())
|
||||
} returns mockk()
|
||||
|
||||
|
||||
test("지난 날짜이면 예외를 던진다.") {
|
||||
val reservationRequest = ReservationFixture.createRequest().copy(
|
||||
date = LocalDate.now().minusDays(1)
|
||||
)
|
||||
|
||||
every {
|
||||
reservationTimeService.findTimeById(any())
|
||||
} returns ReservationTimeFixture.create()
|
||||
|
||||
shouldThrow<RoomescapeException> {
|
||||
reservationService.addReservation(reservationRequest, 1L)
|
||||
}.also {
|
||||
it.errorType shouldBe ErrorType.RESERVATION_PERIOD_IN_PAST
|
||||
}
|
||||
}
|
||||
|
||||
test("지난 시간이면 예외를 던진다.") {
|
||||
val reservationRequest = ReservationFixture.createRequest().copy(
|
||||
date = LocalDate.now(),
|
||||
)
|
||||
|
||||
every {
|
||||
reservationTimeService.findTimeById(reservationRequest.timeId)
|
||||
} returns ReservationTimeFixture.create(
|
||||
startAt = LocalTime.now().minusMinutes(1)
|
||||
)
|
||||
|
||||
shouldThrow<RoomescapeException> {
|
||||
reservationService.addReservation(reservationRequest, 1L)
|
||||
}.also {
|
||||
it.errorType shouldBe ErrorType.RESERVATION_PERIOD_IN_PAST
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
context("예약 대기를 걸 때") {
|
||||
test("이미 예약한 회원이 같은 날짜와 테마로 대기를 걸면 예외를 던진다.") {
|
||||
val reservationRequest = ReservationFixture.createRequest().copy(
|
||||
date = LocalDate.now(),
|
||||
themeId = 1L,
|
||||
timeId = 1L,
|
||||
)
|
||||
|
||||
every {
|
||||
reservationRepository.exists(any())
|
||||
} returns true
|
||||
|
||||
shouldThrow<RoomescapeException> {
|
||||
val waitingRequest = ReservationFixture.createWaitingRequest(
|
||||
date = reservationRequest.date,
|
||||
themeId = reservationRequest.themeId,
|
||||
timeId = reservationRequest.timeId
|
||||
)
|
||||
reservationService.addWaiting(waitingRequest, 1L)
|
||||
}.also {
|
||||
it.errorType shouldBe ErrorType.HAS_RESERVATION_OR_WAITING
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
context("예약을 조회할 때") {
|
||||
test("종료 날짜가 시작 날짜보다 이전이면 예외를 던진다.") {
|
||||
val startFrom = LocalDate.now()
|
||||
val endAt = startFrom.minusDays(1)
|
||||
|
||||
shouldThrow<RoomescapeException> {
|
||||
reservationService.findFilteredReservations(
|
||||
null,
|
||||
null,
|
||||
startFrom,
|
||||
endAt
|
||||
)
|
||||
}.also {
|
||||
it.errorType shouldBe ErrorType.INVALID_DATE_RANGE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
context("대기중인 예약을 승인할 때") {
|
||||
test("관리자가 아니면 예외를 던진다.") {
|
||||
val member = MemberFixture.create(id = 1L, role = Role.MEMBER)
|
||||
|
||||
every {
|
||||
memberService.findById(any())
|
||||
} returns member
|
||||
|
||||
shouldThrow<RoomescapeException> {
|
||||
reservationService.approveWaiting(1L, member.id!!)
|
||||
}.also {
|
||||
it.errorType shouldBe ErrorType.PERMISSION_DOES_NOT_EXIST
|
||||
}
|
||||
}
|
||||
|
||||
test("이미 확정된 예약이 있으면 예외를 던진다.") {
|
||||
val member = MemberFixture.create(id = 1L, role = Role.ADMIN)
|
||||
val reservationId = 1L
|
||||
|
||||
every {
|
||||
memberService.findById(any())
|
||||
} returns member
|
||||
|
||||
every {
|
||||
reservationRepository.isExistConfirmedReservation(reservationId)
|
||||
} returns true
|
||||
|
||||
shouldThrow<RoomescapeException> {
|
||||
reservationService.approveWaiting(reservationId, member.id!!)
|
||||
}.also {
|
||||
it.errorType shouldBe ErrorType.RESERVATION_DUPLICATED
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -11,6 +11,8 @@ import roomescape.payment.web.PaymentCancel
|
||||
import roomescape.reservation.infrastructure.persistence.ReservationEntity
|
||||
import roomescape.reservation.infrastructure.persistence.ReservationStatus
|
||||
import roomescape.reservation.infrastructure.persistence.ReservationTimeEntity
|
||||
import roomescape.reservation.web.ReservationRequest
|
||||
import roomescape.reservation.web.WaitingRequest
|
||||
import roomescape.theme.infrastructure.persistence.ThemeEntity
|
||||
import java.time.LocalDate
|
||||
import java.time.LocalTime
|
||||
@ -76,6 +78,34 @@ object ReservationFixture {
|
||||
member: MemberEntity = MemberFixture.create(),
|
||||
status: ReservationStatus = ReservationStatus.CONFIRMED_PAYMENT_REQUIRED
|
||||
): ReservationEntity = ReservationEntity(id, date, reservationTime, theme, member, status)
|
||||
|
||||
fun createRequest(
|
||||
date: LocalDate = LocalDate.now().plusWeeks(1),
|
||||
themeId: Long = 1L,
|
||||
timeId: Long = 1L,
|
||||
paymentKey: String = "paymentKey",
|
||||
orderId: String = "orderId",
|
||||
amount: Long = 10000L,
|
||||
paymentType: String = "NORMAL",
|
||||
): ReservationRequest = ReservationRequest(
|
||||
date = date,
|
||||
timeId = timeId,
|
||||
themeId = themeId,
|
||||
paymentKey = paymentKey,
|
||||
orderId = orderId,
|
||||
amount = amount,
|
||||
paymentType = paymentType
|
||||
)
|
||||
|
||||
fun createWaitingRequest(
|
||||
date: LocalDate = LocalDate.now().plusWeeks(1),
|
||||
themeId: Long = 1L,
|
||||
timeId: Long = 1L
|
||||
): WaitingRequest = WaitingRequest(
|
||||
date = date,
|
||||
timeId = timeId,
|
||||
themeId = themeId
|
||||
)
|
||||
}
|
||||
|
||||
object JwtFixture {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user