fix(live): 라이브 예약 트랜잭션 경계를 보강한다
This commit is contained in:
@@ -29,6 +29,7 @@ class LiveReservationService(
|
||||
@Value("\${cloud.aws.cloud-front.host}")
|
||||
private val cloudFrontHost: String
|
||||
) {
|
||||
@Transactional
|
||||
fun makeReservation(request: MakeLiveReservationRequest, memberId: Long): MakeLiveReservationResponse {
|
||||
val room = liveRoomRepository.findByIdOrNull(id = request.roomId)
|
||||
?: throw SodaException(messageKey = "live.reservation.invalid_request_retry")
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
package kr.co.vividnext.sodalive.live.reservation
|
||||
|
||||
import kr.co.vividnext.sodalive.live.room.LiveRoom
|
||||
import kr.co.vividnext.sodalive.member.Member
|
||||
import kr.co.vividnext.sodalive.support.EmbeddedRedisInitializer
|
||||
import org.junit.jupiter.api.AfterEach
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
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.mock.web.MockHttpServletRequest
|
||||
import org.springframework.test.annotation.DirtiesContext
|
||||
import org.springframework.test.context.ContextConfiguration
|
||||
import org.springframework.transaction.annotation.Propagation
|
||||
import org.springframework.transaction.annotation.Transactional
|
||||
import org.springframework.transaction.support.TransactionTemplate
|
||||
import org.springframework.web.context.request.RequestContextHolder
|
||||
import org.springframework.web.context.request.ServletRequestAttributes
|
||||
import java.time.LocalDateTime
|
||||
import javax.persistence.EntityManager
|
||||
|
||||
@SpringBootTest(
|
||||
properties = [
|
||||
"spring.cache.type=none",
|
||||
"spring.datasource.url=jdbc:h2:mem:live-reservation-service-integration;" +
|
||||
"MODE=MySQL;DATABASE_TO_UPPER=false;NON_KEYWORDS=VALUE;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE"
|
||||
]
|
||||
)
|
||||
@ContextConfiguration(initializers = [EmbeddedRedisInitializer::class])
|
||||
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
|
||||
@Transactional(propagation = Propagation.NOT_SUPPORTED)
|
||||
class LiveReservationServiceIntegrationTest @Autowired constructor(
|
||||
private val service: LiveReservationService,
|
||||
private val repository: LiveReservationRepository,
|
||||
private val transactionTemplate: TransactionTemplate,
|
||||
private val entityManager: EntityManager
|
||||
) {
|
||||
@BeforeEach
|
||||
fun setUpRequestContext() {
|
||||
RequestContextHolder.setRequestAttributes(ServletRequestAttributes(MockHttpServletRequest()))
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
fun resetRequestContext() {
|
||||
RequestContextHolder.resetRequestAttributes()
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("라이브 예약은 OSIV off 환경에서도 lazy reservations 접근까지 완료된다")
|
||||
fun shouldMakeReservationThroughTransactionalServiceProxyWhenOpenInViewIsDisabled() {
|
||||
val fixture = createFixture()
|
||||
|
||||
val response = service.makeReservation(
|
||||
request = MakeLiveReservationRequest(
|
||||
roomId = fixture.roomId,
|
||||
container = "web",
|
||||
timezone = "Asia/Seoul"
|
||||
),
|
||||
memberId = fixture.memberId
|
||||
)
|
||||
|
||||
val savedReservation = transactionTemplate.execute {
|
||||
val reservation = repository.findById(response.reservationId).orElseThrow()
|
||||
SavedReservation(
|
||||
roomId = reservation.room!!.id!!,
|
||||
memberId = reservation.member!!.id!!
|
||||
)
|
||||
}!!
|
||||
|
||||
assertEquals(fixture.roomId, savedReservation.roomId)
|
||||
assertEquals(fixture.memberId, savedReservation.memberId)
|
||||
}
|
||||
|
||||
private fun createFixture(): Fixture {
|
||||
return transactionTemplate.execute {
|
||||
val creator = Member(
|
||||
email = "live-reservation-creator@test.com",
|
||||
password = "password",
|
||||
nickname = "live-reservation-creator"
|
||||
)
|
||||
entityManager.persist(creator)
|
||||
|
||||
val member = Member(
|
||||
email = "live-reservation-member@test.com",
|
||||
password = "password",
|
||||
nickname = "live-reservation-member"
|
||||
)
|
||||
entityManager.persist(member)
|
||||
|
||||
val room = LiveRoom(
|
||||
title = "예약 라이브",
|
||||
notice = "예약 라이브 안내",
|
||||
beginDateTime = LocalDateTime.now().plusDays(1),
|
||||
numberOfPeople = 10,
|
||||
isAdult = false
|
||||
)
|
||||
room.member = creator
|
||||
entityManager.persist(room)
|
||||
|
||||
entityManager.flush()
|
||||
val fixture = Fixture(
|
||||
roomId = room.id!!,
|
||||
memberId = member.id!!
|
||||
)
|
||||
entityManager.clear()
|
||||
fixture
|
||||
}!!
|
||||
}
|
||||
|
||||
private data class Fixture(
|
||||
val roomId: Long,
|
||||
val memberId: Long
|
||||
)
|
||||
|
||||
private data class SavedReservation(
|
||||
val roomId: Long,
|
||||
val memberId: Long
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user