generated from pricelees/issue-pr-template
[#30] 코드 구조 개선 #31
@ -16,4 +16,7 @@ class TimeWithAvailability(
|
||||
startAt = startAt,
|
||||
isAvailable = isReservable
|
||||
)
|
||||
|
||||
// for test
|
||||
fun canReserve(): Boolean = isReservable
|
||||
}
|
||||
|
||||
@ -1,38 +1,42 @@
|
||||
package roomescape.time.business
|
||||
|
||||
import io.kotest.assertions.assertSoftly
|
||||
import io.kotest.assertions.throwables.shouldNotThrow
|
||||
import io.kotest.assertions.throwables.shouldThrow
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
import io.kotest.matchers.collections.shouldContainExactly
|
||||
import io.kotest.matchers.collections.shouldHaveSize
|
||||
import io.kotest.matchers.shouldBe
|
||||
import io.mockk.Runs
|
||||
import io.mockk.every
|
||||
import io.mockk.just
|
||||
import io.mockk.mockk
|
||||
import org.springframework.data.repository.findByIdOrNull
|
||||
import roomescape.reservation.infrastructure.persistence.ReservationRepository
|
||||
import roomescape.theme.business.domain.TimeWithAvailability
|
||||
import roomescape.theme.exception.ThemeErrorCode
|
||||
import roomescape.theme.exception.ThemeException
|
||||
import roomescape.time.exception.TimeErrorCode
|
||||
import roomescape.time.exception.TimeException
|
||||
import roomescape.time.infrastructure.persistence.TimeRepository
|
||||
import roomescape.time.implement.TimeFinder
|
||||
import roomescape.time.implement.TimeWriter
|
||||
import roomescape.time.infrastructure.persistence.TimeEntity
|
||||
import roomescape.time.web.TimeCreateRequest
|
||||
import roomescape.util.TsidFactory
|
||||
import roomescape.util.TimeFixture
|
||||
import java.time.LocalDate
|
||||
import java.time.LocalTime
|
||||
|
||||
class TimeServiceTest : FunSpec({
|
||||
val timeRepository: TimeRepository = mockk()
|
||||
val reservationRepository: ReservationRepository = mockk()
|
||||
val timeFinder: TimeFinder = mockk()
|
||||
val timeWriter: TimeWriter = mockk()
|
||||
|
||||
val timeService = TimeService(
|
||||
tsidFactory = TsidFactory,
|
||||
timeRepository = timeRepository,
|
||||
reservationRepository = reservationRepository
|
||||
)
|
||||
val timeService = TimeService(timeFinder, timeWriter)
|
||||
|
||||
context("findTimeById") {
|
||||
context("findById") {
|
||||
test("시간을 찾을 수 없으면 예외 응답") {
|
||||
val id = 1L
|
||||
|
||||
every { timeRepository.findByIdOrNull(id) } returns null
|
||||
every {
|
||||
timeFinder.findById(id)
|
||||
} throws TimeException(TimeErrorCode.TIME_NOT_FOUND)
|
||||
|
||||
shouldThrow<TimeException> {
|
||||
timeService.findById(id)
|
||||
@ -42,22 +46,81 @@ class TimeServiceTest : FunSpec({
|
||||
}
|
||||
}
|
||||
|
||||
context("findTimes") {
|
||||
test("정상 응답") {
|
||||
val times: List<TimeEntity> = listOf(
|
||||
TimeFixture.create(startAt = LocalTime.now()),
|
||||
TimeFixture.create(startAt = LocalTime.now().plusMinutes(1)),
|
||||
TimeFixture.create(startAt = LocalTime.now().plusMinutes(2))
|
||||
)
|
||||
|
||||
every {
|
||||
timeFinder.findAll()
|
||||
} returns times
|
||||
|
||||
val response = timeService.findTimes()
|
||||
|
||||
assertSoftly(response.times) {
|
||||
it shouldHaveSize times.size
|
||||
it.map { time -> time.startAt } shouldContainExactly times.map { time -> time.startAt }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
context("findTimesWithAvailability") {
|
||||
val date = LocalDate.now()
|
||||
val themeId = 1L
|
||||
|
||||
test("정상 응답") {
|
||||
val times: List<TimeWithAvailability> = listOf(
|
||||
TimeWithAvailability(1, LocalTime.now(), date, themeId, true),
|
||||
TimeWithAvailability(2, LocalTime.now().plusMinutes(1), date, themeId, false),
|
||||
TimeWithAvailability(3, LocalTime.now().plusMinutes(2), date, themeId, true)
|
||||
)
|
||||
|
||||
every {
|
||||
timeFinder.findAllWithAvailabilityByDateAndThemeId(date, themeId)
|
||||
} returns times
|
||||
|
||||
val response = timeService.findTimesWithAvailability(date, themeId)
|
||||
|
||||
assertSoftly(response.times) {
|
||||
it shouldHaveSize times.size
|
||||
it.map { time -> time.isAvailable } shouldContainExactly times.map { time -> time.canReserve() }
|
||||
}
|
||||
}
|
||||
|
||||
test("테마를 찾을 수 없으면 예외 응답") {
|
||||
every {
|
||||
timeFinder.findAllWithAvailabilityByDateAndThemeId(date, themeId)
|
||||
} throws ThemeException(ThemeErrorCode.THEME_NOT_FOUND)
|
||||
|
||||
shouldThrow<ThemeException> {
|
||||
timeService.findTimesWithAvailability(date, themeId)
|
||||
}.also {
|
||||
it.errorCode shouldBe ThemeErrorCode.THEME_NOT_FOUND
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
context("createTime") {
|
||||
val request = TimeCreateRequest(startAt = LocalTime.of(10, 0))
|
||||
|
||||
test("정상 저장") {
|
||||
every { timeRepository.existsByStartAt(request.startAt) } returns false
|
||||
every { timeRepository.save(any()) } returns TimeFixture.create(
|
||||
id = 1L,
|
||||
startAt = request.startAt
|
||||
)
|
||||
val time: TimeEntity = TimeFixture.create(startAt = request.startAt)
|
||||
|
||||
every {
|
||||
timeWriter.create(request.startAt)
|
||||
} returns time
|
||||
|
||||
val response = timeService.createTime(request)
|
||||
response.id shouldBe 1L
|
||||
response.id shouldBe time.id
|
||||
}
|
||||
|
||||
test("중복된 시간이 있으면 예외 응답") {
|
||||
every { timeRepository.existsByStartAt(request.startAt) } returns true
|
||||
every {
|
||||
timeWriter.create(request.startAt)
|
||||
} throws TimeException(TimeErrorCode.TIME_DUPLICATED)
|
||||
|
||||
shouldThrow<TimeException> {
|
||||
timeService.createTime(request)
|
||||
@ -67,14 +130,13 @@ class TimeServiceTest : FunSpec({
|
||||
}
|
||||
}
|
||||
|
||||
context("removeTimeById") {
|
||||
context("deleteTime") {
|
||||
test("정상 제거 및 응답") {
|
||||
val id = 1L
|
||||
val time = TimeFixture.create(id = id)
|
||||
|
||||
every { timeRepository.findByIdOrNull(id) } returns time
|
||||
every { reservationRepository.findAllByTime(time) } returns emptyList()
|
||||
every { timeRepository.delete(time) } just Runs
|
||||
every { timeFinder.findById(id) } returns time
|
||||
every { timeWriter.delete(time) } just Runs
|
||||
|
||||
shouldNotThrow<Exception> {
|
||||
timeService.deleteTime(id)
|
||||
@ -84,7 +146,7 @@ class TimeServiceTest : FunSpec({
|
||||
test("시간을 찾을 수 없으면 예외 응답") {
|
||||
val id = 1L
|
||||
|
||||
every { timeRepository.findByIdOrNull(id) } returns null
|
||||
every { timeFinder.findById(id) } throws TimeException(TimeErrorCode.TIME_NOT_FOUND)
|
||||
|
||||
shouldThrow<TimeException> {
|
||||
timeService.deleteTime(id)
|
||||
@ -97,9 +159,8 @@ class TimeServiceTest : FunSpec({
|
||||
val id = 1L
|
||||
val time = TimeFixture.create()
|
||||
|
||||
every { timeRepository.findByIdOrNull(id) } returns time
|
||||
|
||||
every { reservationRepository.findAllByTime(time) } returns listOf(mockk())
|
||||
every { timeFinder.findById(id) } returns time
|
||||
every { timeWriter.delete(time) } throws TimeException(TimeErrorCode.TIME_ALREADY_RESERVED)
|
||||
|
||||
shouldThrow<TimeException> {
|
||||
timeService.deleteTime(id)
|
||||
|
||||
109
src/test/kotlin/roomescape/time/implement/TimeFinderTest.kt
Normal file
109
src/test/kotlin/roomescape/time/implement/TimeFinderTest.kt
Normal file
@ -0,0 +1,109 @@
|
||||
package roomescape.time.implement
|
||||
|
||||
import io.kotest.assertions.assertSoftly
|
||||
import io.kotest.assertions.throwables.shouldThrow
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
import io.kotest.matchers.collections.shouldHaveSize
|
||||
import io.kotest.matchers.shouldBe
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.verify
|
||||
import org.springframework.data.repository.findByIdOrNull
|
||||
import roomescape.reservation.implement.ReservationFinder
|
||||
import roomescape.theme.business.domain.TimeWithAvailability
|
||||
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.infrastructure.persistence.TimeRepository
|
||||
import roomescape.util.TimeFixture
|
||||
import java.time.LocalDate
|
||||
import java.time.LocalTime
|
||||
|
||||
class TimeFinderTest : FunSpec({
|
||||
val timeRepository: TimeRepository = mockk()
|
||||
val reservationFinder: ReservationFinder = mockk()
|
||||
val themeFinder: ThemeFinder = mockk()
|
||||
|
||||
val timeFinder = TimeFinder(timeRepository, reservationFinder, themeFinder)
|
||||
|
||||
context("findAll") {
|
||||
test("모든 시간을 조회한다.") {
|
||||
every {
|
||||
timeRepository.findAll()
|
||||
} returns listOf(mockk(), mockk(), mockk())
|
||||
|
||||
timeRepository.findAll() shouldHaveSize 3
|
||||
}
|
||||
}
|
||||
|
||||
context("findById") {
|
||||
val timeId = 1L
|
||||
test("동일한 ID인 시간을 찾아 응답한다.") {
|
||||
every {
|
||||
timeRepository.findByIdOrNull(timeId)
|
||||
} returns mockk()
|
||||
|
||||
timeFinder.findById(timeId)
|
||||
|
||||
verify(exactly = 1) {
|
||||
timeRepository.findByIdOrNull(timeId)
|
||||
}
|
||||
}
|
||||
|
||||
test("동일한 ID인 시간이 없으면 실패한다.") {
|
||||
every {
|
||||
timeRepository.findByIdOrNull(timeId)
|
||||
} returns null
|
||||
|
||||
shouldThrow<TimeException> {
|
||||
timeFinder.findById(timeId)
|
||||
}.also {
|
||||
it.errorCode shouldBe TimeErrorCode.TIME_NOT_FOUND
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
context("findAllWithAvailabilityByDateAndThemeId") {
|
||||
val date = LocalDate.now()
|
||||
val themeId = 1L
|
||||
|
||||
test("테마를 찾을 수 없으면 실패한다.") {
|
||||
every {
|
||||
themeFinder.findById(themeId)
|
||||
} throws ThemeException(ThemeErrorCode.THEME_NOT_FOUND)
|
||||
|
||||
shouldThrow<ThemeException> {
|
||||
timeFinder.findAllWithAvailabilityByDateAndThemeId(date, themeId)
|
||||
}.also {
|
||||
it.errorCode shouldBe ThemeErrorCode.THEME_NOT_FOUND
|
||||
}
|
||||
}
|
||||
|
||||
test("날짜, 테마에 맞는 예약 자체가 없으면 모든 시간이 예약 가능하다.") {
|
||||
every {
|
||||
themeFinder.findById(themeId)
|
||||
} returns mockk()
|
||||
|
||||
every {
|
||||
reservationFinder.findAllByDateAndTheme(date, any())
|
||||
} returns emptyList()
|
||||
|
||||
every {
|
||||
timeRepository.findAll()
|
||||
} returns listOf(
|
||||
TimeFixture.create(startAt = LocalTime.now()),
|
||||
TimeFixture.create(startAt = LocalTime.now().plusMinutes(30))
|
||||
)
|
||||
|
||||
val result: List<TimeWithAvailability> =
|
||||
timeFinder.findAllWithAvailabilityByDateAndThemeId(date, themeId)
|
||||
|
||||
assertSoftly(result) {
|
||||
it shouldHaveSize 2
|
||||
it.all { time -> time.canReserve() }
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -0,0 +1,74 @@
|
||||
package roomescape.time.implement
|
||||
|
||||
import io.kotest.assertions.throwables.shouldNotThrow
|
||||
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.reservation.implement.ReservationFinder
|
||||
import roomescape.time.exception.TimeErrorCode
|
||||
import roomescape.time.exception.TimeException
|
||||
import roomescape.time.infrastructure.persistence.TimeEntity
|
||||
import roomescape.time.infrastructure.persistence.TimeRepository
|
||||
import roomescape.util.TimeFixture
|
||||
import java.time.LocalTime
|
||||
|
||||
class TimeValidatorTest : FunSpec({
|
||||
val timeRepository: TimeRepository = mockk()
|
||||
val reservationFinder: ReservationFinder = mockk()
|
||||
|
||||
val timeValidator = TimeValidator(timeRepository, reservationFinder)
|
||||
|
||||
context("validateIsAlreadyExists") {
|
||||
val startAt = LocalTime.now()
|
||||
|
||||
test("같은 이메일을 가진 회원이 있으면 예외를 던진다.") {
|
||||
every {
|
||||
timeRepository.existsByStartAt(startAt)
|
||||
} returns true
|
||||
|
||||
shouldThrow<TimeException> {
|
||||
timeValidator.validateIsAlreadyExists(startAt)
|
||||
}.also {
|
||||
it.errorCode shouldBe TimeErrorCode.TIME_DUPLICATED
|
||||
}
|
||||
}
|
||||
|
||||
test("같은 이메일을 가진 회원이 없으면 종료한다.") {
|
||||
every {
|
||||
timeRepository.existsByStartAt(startAt)
|
||||
} returns false
|
||||
|
||||
shouldNotThrow<TimeException> {
|
||||
timeValidator.validateIsAlreadyExists(startAt)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
context("validateIsReserved") {
|
||||
val time: TimeEntity = TimeFixture.create(startAt = LocalTime.now())
|
||||
|
||||
test("해당 시간에 예약이 있으면 예외를 던진다.") {
|
||||
every {
|
||||
reservationFinder.isTimeReserved(time)
|
||||
} returns true
|
||||
|
||||
shouldThrow<TimeException> {
|
||||
timeValidator.validateIsReserved(time)
|
||||
}.also {
|
||||
it.errorCode shouldBe TimeErrorCode.TIME_ALREADY_RESERVED
|
||||
}
|
||||
}
|
||||
|
||||
test("해당 시간에 예약이 없으면 종료한다.") {
|
||||
every {
|
||||
reservationFinder.isTimeReserved(time)
|
||||
} returns false
|
||||
|
||||
shouldNotThrow<TimeException> {
|
||||
timeValidator.validateIsReserved(time)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
84
src/test/kotlin/roomescape/time/implement/TimeWriterTest.kt
Normal file
84
src/test/kotlin/roomescape/time/implement/TimeWriterTest.kt
Normal file
@ -0,0 +1,84 @@
|
||||
package roomescape.time.implement
|
||||
|
||||
import io.kotest.assertions.throwables.shouldThrow
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
import io.kotest.matchers.shouldBe
|
||||
import io.mockk.*
|
||||
import roomescape.time.exception.TimeErrorCode
|
||||
import roomescape.time.exception.TimeException
|
||||
import roomescape.time.infrastructure.persistence.TimeEntity
|
||||
import roomescape.time.infrastructure.persistence.TimeRepository
|
||||
import roomescape.util.TimeFixture
|
||||
import roomescape.util.TsidFactory
|
||||
import java.time.LocalTime
|
||||
|
||||
class TimeWriterTest : FunSpec({
|
||||
|
||||
val timeValidator: TimeValidator = mockk()
|
||||
val timeRepository: TimeRepository = mockk()
|
||||
|
||||
val timeWriter = TimeWriter(timeValidator, timeRepository, TsidFactory)
|
||||
|
||||
context("create") {
|
||||
val startAt = LocalTime.now()
|
||||
|
||||
test("중복된 시간이 있으면 실패한다.") {
|
||||
every {
|
||||
timeValidator.validateIsAlreadyExists(startAt)
|
||||
} throws TimeException(TimeErrorCode.TIME_DUPLICATED)
|
||||
|
||||
shouldThrow<TimeException> {
|
||||
timeWriter.create(startAt)
|
||||
}.also {
|
||||
it.errorCode shouldBe TimeErrorCode.TIME_DUPLICATED
|
||||
}
|
||||
}
|
||||
|
||||
test("중복된 시간이 없으면 저장한다.") {
|
||||
every {
|
||||
timeValidator.validateIsAlreadyExists(startAt)
|
||||
} just Runs
|
||||
|
||||
every {
|
||||
timeRepository.save(any())
|
||||
} returns TimeFixture.create(startAt = startAt)
|
||||
|
||||
timeWriter.create(startAt)
|
||||
|
||||
verify(exactly = 1) {
|
||||
timeRepository.save(any())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
context("delete") {
|
||||
val time: TimeEntity = TimeFixture.create()
|
||||
test("예약이 있는 시간이면 실패한다.") {
|
||||
every {
|
||||
timeValidator.validateIsReserved(time)
|
||||
} throws TimeException(TimeErrorCode.TIME_ALREADY_RESERVED)
|
||||
|
||||
shouldThrow<TimeException> {
|
||||
timeWriter.delete(time)
|
||||
}.also {
|
||||
it.errorCode shouldBe TimeErrorCode.TIME_ALREADY_RESERVED
|
||||
}
|
||||
}
|
||||
|
||||
test("예약이 없는 시간이면 제거한다.") {
|
||||
every {
|
||||
timeValidator.validateIsReserved(time)
|
||||
} just Runs
|
||||
|
||||
every {
|
||||
timeRepository.delete(time)
|
||||
} just Runs
|
||||
|
||||
timeWriter.delete(time)
|
||||
|
||||
verify(exactly = 1) {
|
||||
timeRepository.delete(time)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -1,28 +1,21 @@
|
||||
package roomescape.time.web
|
||||
|
||||
import com.ninjasquad.springmockk.MockkBean
|
||||
import com.ninjasquad.springmockk.SpykBean
|
||||
import io.kotest.assertions.assertSoftly
|
||||
import io.kotest.matchers.collections.shouldHaveSize
|
||||
import io.kotest.matchers.shouldBe
|
||||
import io.mockk.every
|
||||
import org.hamcrest.Matchers.equalTo
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest
|
||||
import org.springframework.context.annotation.Import
|
||||
import org.springframework.data.jpa.mapping.JpaMetamodelMappingContext
|
||||
import org.springframework.data.repository.findByIdOrNull
|
||||
import org.springframework.http.MediaType
|
||||
import org.springframework.test.web.servlet.MockMvc
|
||||
import roomescape.auth.exception.AuthErrorCode
|
||||
import roomescape.common.config.JacksonConfig
|
||||
import roomescape.reservation.infrastructure.persistence.ReservationRepository
|
||||
import roomescape.theme.exception.ThemeErrorCode
|
||||
import roomescape.theme.exception.ThemeException
|
||||
import roomescape.time.business.TimeService
|
||||
import roomescape.time.exception.TimeErrorCode
|
||||
import roomescape.time.infrastructure.persistence.TimeEntity
|
||||
import roomescape.time.infrastructure.persistence.TimeRepository
|
||||
import roomescape.util.ReservationFixture
|
||||
import roomescape.time.exception.TimeException
|
||||
import roomescape.util.RoomescapeApiTest
|
||||
import roomescape.util.ThemeFixture
|
||||
import roomescape.util.TimeFixture
|
||||
import java.time.LocalDate
|
||||
import java.time.LocalTime
|
||||
@ -32,15 +25,9 @@ class TimeControllerTest(
|
||||
val mockMvc: MockMvc,
|
||||
) : RoomescapeApiTest() {
|
||||
|
||||
@SpykBean
|
||||
@MockkBean
|
||||
private lateinit var timeService: TimeService
|
||||
|
||||
@MockkBean
|
||||
private lateinit var timeRepository: TimeRepository
|
||||
|
||||
@MockkBean
|
||||
private lateinit var reservationRepository: ReservationRepository
|
||||
|
||||
init {
|
||||
Given("등록된 모든 시간을 조회할 때") {
|
||||
val endpoint = "/times"
|
||||
@ -52,11 +39,11 @@ class TimeControllerTest(
|
||||
|
||||
Then("정상 응답") {
|
||||
every {
|
||||
timeRepository.findAll()
|
||||
timeService.findTimes()
|
||||
} returns listOf(
|
||||
TimeFixture.create(id = 1L),
|
||||
TimeFixture.create(id = 2L)
|
||||
)
|
||||
).toResponse()
|
||||
|
||||
runGetTest(
|
||||
mockMvc = mockMvc,
|
||||
@ -76,7 +63,7 @@ class TimeControllerTest(
|
||||
loginAsUser()
|
||||
val expectedError = AuthErrorCode.ACCESS_DENIED
|
||||
|
||||
Then("에러 응답을 받는다.") {
|
||||
Then("예외 응답") {
|
||||
runGetTest(
|
||||
mockMvc = mockMvc,
|
||||
endpoint = endpoint,
|
||||
@ -85,7 +72,7 @@ class TimeControllerTest(
|
||||
}.andExpect {
|
||||
content {
|
||||
contentType(MediaType.APPLICATION_JSON)
|
||||
jsonPath("$.code") { value(expectedError.errorCode) }
|
||||
jsonPath("$.code") { equalTo(expectedError.errorCode) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -139,8 +126,8 @@ class TimeControllerTest(
|
||||
Then("동일한 시간이 존재하면 예외 응답") {
|
||||
val expectedError = TimeErrorCode.TIME_DUPLICATED
|
||||
every {
|
||||
timeRepository.existsByStartAt(time)
|
||||
} returns true
|
||||
timeService.createTime(request)
|
||||
} throws TimeException(expectedError)
|
||||
|
||||
runPostTest(
|
||||
mockMvc = mockMvc,
|
||||
@ -150,7 +137,7 @@ class TimeControllerTest(
|
||||
status { isEqualTo(expectedError.httpStatus.value()) }
|
||||
content {
|
||||
contentType(MediaType.APPLICATION_JSON)
|
||||
jsonPath("$.code") { value(expectedError.errorCode) }
|
||||
jsonPath("$.code") { equalTo(expectedError.errorCode) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -159,7 +146,7 @@ class TimeControllerTest(
|
||||
When("관리자가 아닌 경우") {
|
||||
loginAsUser()
|
||||
|
||||
Then("에러 응답을 받는다.") {
|
||||
Then("예외 응답") {
|
||||
val expectedError = AuthErrorCode.ACCESS_DENIED
|
||||
runPostTest(
|
||||
mockMvc = mockMvc,
|
||||
@ -197,9 +184,10 @@ class TimeControllerTest(
|
||||
Then("없는 시간을 조회하면 예외 응답") {
|
||||
val id = 1L
|
||||
val expectedError = TimeErrorCode.TIME_NOT_FOUND
|
||||
|
||||
every {
|
||||
timeRepository.findByIdOrNull(id)
|
||||
} returns null
|
||||
timeService.deleteTime(id)
|
||||
} throws TimeException(expectedError)
|
||||
|
||||
runDeleteTest(
|
||||
mockMvc = mockMvc,
|
||||
@ -208,7 +196,7 @@ class TimeControllerTest(
|
||||
status { isEqualTo(expectedError.httpStatus.value()) }
|
||||
content {
|
||||
contentType(MediaType.APPLICATION_JSON)
|
||||
jsonPath("$.code") { value(expectedError.errorCode) }
|
||||
jsonPath("$.code") { equalTo(expectedError.errorCode) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -216,13 +204,10 @@ class TimeControllerTest(
|
||||
Then("예약이 있는 시간을 삭제하면 예외 응답") {
|
||||
val id = 1L
|
||||
val expectedError = TimeErrorCode.TIME_ALREADY_RESERVED
|
||||
every {
|
||||
timeRepository.findByIdOrNull(id)
|
||||
} returns TimeFixture.create(id = id)
|
||||
|
||||
every {
|
||||
reservationRepository.findAllByTime(any())
|
||||
} returns listOf(ReservationFixture.create())
|
||||
timeService.deleteTime(id)
|
||||
} throws TimeException(expectedError)
|
||||
|
||||
runDeleteTest(
|
||||
mockMvc = mockMvc,
|
||||
@ -231,7 +216,7 @@ class TimeControllerTest(
|
||||
status { isEqualTo(expectedError.httpStatus.value()) }
|
||||
content {
|
||||
contentType(MediaType.APPLICATION_JSON)
|
||||
jsonPath("$.code") { value(expectedError.errorCode) }
|
||||
jsonPath("$.code") { equalTo(expectedError.errorCode) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -240,7 +225,7 @@ class TimeControllerTest(
|
||||
When("관리자가 아닌 경우") {
|
||||
loginAsUser()
|
||||
|
||||
Then("에러 응답을 받는다.") {
|
||||
Then("예외 응답") {
|
||||
val expectedError = AuthErrorCode.ACCESS_DENIED
|
||||
runDeleteTest(
|
||||
mockMvc = mockMvc,
|
||||
@ -254,35 +239,34 @@ class TimeControllerTest(
|
||||
}
|
||||
|
||||
Given("날짜, 테마가 주어졌을 때") {
|
||||
loginAsUser()
|
||||
|
||||
beforeTest {
|
||||
loginAsUser()
|
||||
}
|
||||
val date: LocalDate = LocalDate.now()
|
||||
val themeId = 1L
|
||||
|
||||
When("저장된 예약 시간이 있으면") {
|
||||
val times: List<TimeEntity> = listOf(
|
||||
TimeFixture.create(id = 1L, startAt = LocalTime.of(10, 0)),
|
||||
TimeFixture.create(id = 2L, startAt = LocalTime.of(11, 0))
|
||||
)
|
||||
|
||||
every {
|
||||
timeRepository.findAll()
|
||||
} returns times
|
||||
|
||||
Then("그 시간과, 해당 날짜와 테마에 대한 예약 여부가 담긴 목록을 응답") {
|
||||
|
||||
every {
|
||||
reservationRepository.findByDateAndThemeId(date, themeId)
|
||||
} returns listOf(
|
||||
ReservationFixture.create(
|
||||
id = 1L,
|
||||
date = date,
|
||||
theme = ThemeFixture.create(id = themeId),
|
||||
time = times[0]
|
||||
When("테마를 찾을 수 있으면") {
|
||||
Then("해당 날짜와 테마에 대한 예약 여부가 담긴 모든 시간을 응답") {
|
||||
val response = TimeWithAvailabilityListResponse(
|
||||
listOf(
|
||||
TimeWithAvailabilityResponse(id = 1L, startAt = LocalTime.now(), isAvailable = true),
|
||||
TimeWithAvailabilityResponse(
|
||||
id = 2L,
|
||||
startAt = LocalTime.now().plusMinutes(30),
|
||||
isAvailable = false
|
||||
),
|
||||
TimeWithAvailabilityResponse(
|
||||
id = 1L,
|
||||
startAt = LocalTime.now().plusHours(1),
|
||||
isAvailable = true
|
||||
),
|
||||
)
|
||||
)
|
||||
every {
|
||||
timeService.findTimesWithAvailability(date, themeId)
|
||||
} returns response
|
||||
|
||||
val response = runGetTest(
|
||||
val result = runGetTest(
|
||||
mockMvc = mockMvc,
|
||||
endpoint = "/times/search?date=$date&themeId=$themeId",
|
||||
) {
|
||||
@ -292,16 +276,33 @@ class TimeControllerTest(
|
||||
}
|
||||
}.andReturn().readValue(TimeWithAvailabilityListResponse::class.java)
|
||||
|
||||
assertSoftly(response.times) {
|
||||
this shouldHaveSize times.size
|
||||
this[0].id shouldBe times[0].id
|
||||
this[0].isAvailable shouldBe false
|
||||
assertSoftly(result.times) {
|
||||
this shouldHaveSize response.times.size
|
||||
this[0].id shouldBe response.times[0].id
|
||||
this[0].isAvailable shouldBe response.times[0].isAvailable
|
||||
|
||||
this[1].id shouldBe times[1].id
|
||||
this[1].isAvailable shouldBe true
|
||||
this[1].id shouldBe response.times[1].id
|
||||
this[1].isAvailable shouldBe response.times[1].isAvailable
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
When("테마를 찾을 수 없으면") {
|
||||
val expectedError = ThemeErrorCode.THEME_NOT_FOUND
|
||||
every {
|
||||
timeService.findTimesWithAvailability(date, themeId)
|
||||
} throws ThemeException(expectedError)
|
||||
|
||||
Then("예외 응답") {
|
||||
runGetTest(
|
||||
mockMvc = mockMvc,
|
||||
endpoint = "/times/search?date=$date&themeId=$themeId",
|
||||
) {
|
||||
status { isNotFound() }
|
||||
jsonPath("$.code", equalTo(expectedError.errorCode))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user