generated from pricelees/issue-pr-template
261 lines
11 KiB
Kotlin
261 lines
11 KiB
Kotlin
package roomescape.reservation.implement
|
|
|
|
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.member.exception.MemberErrorCode
|
|
import roomescape.member.exception.MemberException
|
|
import roomescape.member.implement.MemberFinder
|
|
import roomescape.reservation.exception.ReservationErrorCode
|
|
import roomescape.reservation.exception.ReservationException
|
|
import roomescape.reservation.infrastructure.persistence.ReservationEntity
|
|
import roomescape.reservation.infrastructure.persistence.ReservationRepository
|
|
import roomescape.reservation.infrastructure.persistence.ReservationStatus
|
|
import roomescape.theme.exception.ThemeErrorCode
|
|
import roomescape.theme.exception.ThemeException
|
|
import roomescape.theme.implement.ThemeFinder
|
|
import roomescape.time.exception.TimeErrorCode
|
|
import roomescape.time.exception.TimeException
|
|
import roomescape.time.implement.TimeFinder
|
|
import roomescape.util.MemberFixture
|
|
import roomescape.util.ThemeFixture
|
|
import roomescape.util.TimeFixture
|
|
import roomescape.util.TsidFactory
|
|
import java.time.LocalDate
|
|
import java.time.LocalTime
|
|
|
|
class ReservationWriterTest : FunSpec({
|
|
|
|
val reservationValidator: ReservationValidator = mockk()
|
|
val reservationRepository: ReservationRepository = mockk()
|
|
val memberFinder: MemberFinder = mockk()
|
|
val timeFinder: TimeFinder = mockk()
|
|
val themeFinder: ThemeFinder = mockk()
|
|
|
|
val reservationWriter = ReservationWriter(
|
|
reservationValidator, reservationRepository, memberFinder, timeFinder, themeFinder, TsidFactory
|
|
)
|
|
|
|
context("create") {
|
|
val today = LocalDate.now()
|
|
val timeId = 1L
|
|
val themeId = 1L
|
|
val memberId = 1L
|
|
val status = ReservationStatus.CONFIRMED
|
|
val requesterId = 1L
|
|
|
|
test("시간을 찾을 수 없으면 실패한다.") {
|
|
every {
|
|
timeFinder.findById(any())
|
|
} throws TimeException(TimeErrorCode.TIME_NOT_FOUND)
|
|
|
|
shouldThrow<TimeException> {
|
|
reservationWriter.create(today, timeId, themeId, memberId, status, requesterId)
|
|
}.also {
|
|
it.errorCode shouldBe TimeErrorCode.TIME_NOT_FOUND
|
|
}
|
|
}
|
|
|
|
test("이전 날짜이면 실패한다.") {
|
|
every {
|
|
timeFinder.findById(timeId)
|
|
} returns TimeFixture.create(id = timeId, startAt = LocalTime.now().plusHours(1))
|
|
|
|
every {
|
|
reservationValidator.validateIsPast(any(), any())
|
|
} throws ReservationException(ReservationErrorCode.PAST_REQUEST_DATETIME)
|
|
|
|
shouldThrow<ReservationException> {
|
|
reservationWriter.create(today.minusDays(1), timeId, themeId, memberId, status, requesterId)
|
|
}.also {
|
|
it.errorCode shouldBe ReservationErrorCode.PAST_REQUEST_DATETIME
|
|
}
|
|
}
|
|
|
|
test("테마를 찾을 수 없으면 실패한다.") {
|
|
every { timeFinder.findById(timeId) } returns TimeFixture.create(id = timeId)
|
|
every { reservationValidator.validateIsPast(any(), any()) } returns Unit
|
|
|
|
every {
|
|
themeFinder.findById(themeId)
|
|
} throws ThemeException(ThemeErrorCode.THEME_NOT_FOUND)
|
|
|
|
shouldThrow<ThemeException> {
|
|
reservationWriter.create(today.plusDays(1), timeId, themeId, memberId, status, requesterId)
|
|
}.also {
|
|
it.errorCode shouldBe ThemeErrorCode.THEME_NOT_FOUND
|
|
}
|
|
}
|
|
|
|
test("회원을 찾을 수 없으면 실패한다.") {
|
|
every { timeFinder.findById(timeId) } returns TimeFixture.create(id = timeId)
|
|
every { reservationValidator.validateIsPast(any(), any()) } returns Unit
|
|
every { themeFinder.findById(themeId) } returns ThemeFixture.create(id = themeId)
|
|
|
|
every {
|
|
memberFinder.findById(memberId)
|
|
} throws MemberException(MemberErrorCode.MEMBER_NOT_FOUND)
|
|
|
|
shouldThrow<MemberException> {
|
|
reservationWriter.create(today.plusDays(1), timeId, themeId, memberId, status, requesterId)
|
|
}.also {
|
|
it.errorCode shouldBe MemberErrorCode.MEMBER_NOT_FOUND
|
|
}
|
|
}
|
|
|
|
test("이미 예약이 있는 회원이 대기를 추가하면 실패한다.") {
|
|
every { timeFinder.findById(timeId) } returns TimeFixture.create(id = timeId)
|
|
every { reservationValidator.validateIsPast(any(), any()) } returns Unit
|
|
every { themeFinder.findById(themeId) } returns ThemeFixture.create(id = themeId)
|
|
every { memberFinder.findById(memberId) } returns MemberFixture.create(id = memberId)
|
|
|
|
every {
|
|
reservationValidator.validateMemberAlreadyReserve(themeId, timeId, today, memberId)
|
|
} throws ReservationException(ReservationErrorCode.ALREADY_RESERVE)
|
|
|
|
shouldThrow<ReservationException> {
|
|
reservationWriter.create(today, timeId, themeId, memberId, status = ReservationStatus.WAITING, memberId)
|
|
}.also {
|
|
it.errorCode shouldBe ReservationErrorCode.ALREADY_RESERVE
|
|
}
|
|
}
|
|
|
|
test("동일한 날짜, 시간, 테마인 예약이 이미 있으면 실패한다.") {
|
|
every { timeFinder.findById(timeId) } returns TimeFixture.create(id = timeId)
|
|
every { reservationValidator.validateIsPast(any(), any()) } returns Unit
|
|
every { themeFinder.findById(themeId) } returns ThemeFixture.create(id = themeId)
|
|
every { memberFinder.findById(memberId) } returns MemberFixture.create(id = memberId)
|
|
|
|
every {
|
|
reservationValidator.validateIsAlreadyExists(today, any(), any())
|
|
} throws ReservationException(ReservationErrorCode.RESERVATION_DUPLICATED)
|
|
|
|
shouldThrow<ReservationException> {
|
|
reservationWriter.create(today, timeId, themeId, memberId, status, memberId)
|
|
}.also {
|
|
it.errorCode shouldBe ReservationErrorCode.RESERVATION_DUPLICATED
|
|
}
|
|
}
|
|
|
|
test("예약하려는 회원과 신청한 회원이 다를 때, 신청한 회원을 찾을 수 없으면 실패한다.") {
|
|
every { timeFinder.findById(timeId) } returns TimeFixture.create(id = timeId)
|
|
every { reservationValidator.validateIsPast(any(), any()) } returns Unit
|
|
every { themeFinder.findById(themeId) } returns ThemeFixture.create(id = themeId)
|
|
every { memberFinder.findById(memberId) } returns MemberFixture.create(id = memberId)
|
|
every { reservationValidator.validateIsAlreadyExists(today, any(), any()) } returns Unit
|
|
|
|
every {
|
|
memberFinder.findById(memberId + 1)
|
|
} throws MemberException(MemberErrorCode.MEMBER_NOT_FOUND)
|
|
|
|
shouldThrow<MemberException> {
|
|
reservationWriter.create(
|
|
today,
|
|
timeId,
|
|
themeId,
|
|
memberId = memberId,
|
|
status,
|
|
requesterId = (memberId + 1)
|
|
)
|
|
}.also {
|
|
it.errorCode shouldBe MemberErrorCode.MEMBER_NOT_FOUND
|
|
}
|
|
}
|
|
|
|
test("예약하려는 회원과 신청한 회원이 다를 때, 신청한 회원이 관리자가 아니면 실패한다.") {
|
|
every { timeFinder.findById(timeId) } returns TimeFixture.create(id = timeId)
|
|
every { reservationValidator.validateIsPast(any(), any()) } returns Unit
|
|
every { themeFinder.findById(themeId) } returns ThemeFixture.create(id = themeId)
|
|
every { memberFinder.findById(memberId) } returns MemberFixture.create(id = memberId)
|
|
every { reservationValidator.validateIsAlreadyExists(today, any(), any()) } returns Unit
|
|
|
|
every {
|
|
memberFinder.findById(memberId + 1)
|
|
} returns MemberFixture.create(id = memberId + 1)
|
|
|
|
every {
|
|
reservationValidator.validateCreateAuthority(any())
|
|
} throws ReservationException(ReservationErrorCode.NO_PERMISSION)
|
|
|
|
shouldThrow<ReservationException> {
|
|
reservationWriter.create(
|
|
today,
|
|
timeId,
|
|
themeId,
|
|
memberId = memberId,
|
|
status,
|
|
requesterId = (memberId + 1)
|
|
)
|
|
}.also {
|
|
it.errorCode shouldBe ReservationErrorCode.NO_PERMISSION
|
|
}
|
|
}
|
|
}
|
|
|
|
context("deleteWaiting") {
|
|
val reservation: ReservationEntity = mockk()
|
|
val requesterId = 1L
|
|
|
|
test("대기 상태가 아니면 실패한다.") {
|
|
every {
|
|
reservationValidator.validateIsWaiting(any())
|
|
} throws ReservationException(ReservationErrorCode.ALREADY_CONFIRMED)
|
|
|
|
shouldThrow<ReservationException> {
|
|
reservationWriter.deleteWaiting(reservation, requesterId)
|
|
}.also {
|
|
it.errorCode shouldBe ReservationErrorCode.ALREADY_CONFIRMED
|
|
}
|
|
}
|
|
|
|
test("삭제하려는 회원이 관리자가 아니고, 예약한 회원과 다르면 실패한다.") {
|
|
every { reservationValidator.validateIsWaiting(any()) } returns Unit
|
|
every {
|
|
reservationValidator.validateDeleteAuthority(any(), any())
|
|
} throws ReservationException(ReservationErrorCode.NOT_RESERVATION_OWNER)
|
|
|
|
shouldThrow<ReservationException> {
|
|
reservationWriter.deleteWaiting(reservation, requesterId)
|
|
}.also {
|
|
it.errorCode shouldBe ReservationErrorCode.NOT_RESERVATION_OWNER
|
|
}
|
|
}
|
|
}
|
|
|
|
context("deleteConfirm") {
|
|
val reservation: ReservationEntity = mockk()
|
|
val requesterId = 1L
|
|
|
|
test("삭제하려는 회원이 관리자가 아니고, 예약한 회원과 다르면 실패한다.") {
|
|
every { reservationValidator.validateIsWaiting(any()) } returns Unit
|
|
every {
|
|
reservationValidator.validateDeleteAuthority(any(), any())
|
|
} throws ReservationException(ReservationErrorCode.NOT_RESERVATION_OWNER)
|
|
|
|
shouldThrow<ReservationException> {
|
|
reservationWriter.deleteConfirmed(reservation, requesterId)
|
|
}.also {
|
|
it.errorCode shouldBe ReservationErrorCode.NOT_RESERVATION_OWNER
|
|
}
|
|
}
|
|
}
|
|
|
|
context("confirm") {
|
|
val reservationId = 1L
|
|
|
|
test("승인하려는 대기와 같은 날짜,시간,테마를 가진 확정 예약이 있으면 실패한다.") {
|
|
every {
|
|
reservationValidator.validateAlreadyConfirmed(reservationId)
|
|
} throws ReservationException(ReservationErrorCode.CONFIRMED_RESERVATION_ALREADY_EXISTS)
|
|
|
|
shouldThrow<ReservationException> {
|
|
reservationWriter.confirm(reservationId)
|
|
}.also {
|
|
it.errorCode shouldBe ReservationErrorCode.CONFIRMED_RESERVATION_ALREADY_EXISTS
|
|
}
|
|
}
|
|
}
|
|
})
|