diff --git a/mealkitary-api/src/main/kotlin/com/mealkitary/reservation/web/GetReservationController.kt b/mealkitary-api/src/main/kotlin/com/mealkitary/reservation/web/GetReservationController.kt index 2fb5d2d..cd204dc 100644 --- a/mealkitary-api/src/main/kotlin/com/mealkitary/reservation/web/GetReservationController.kt +++ b/mealkitary-api/src/main/kotlin/com/mealkitary/reservation/web/GetReservationController.kt @@ -5,6 +5,7 @@ import com.mealkitary.common.utils.UUIDUtils import com.mealkitary.reservation.application.port.input.GetReservationQuery import com.mealkitary.reservation.application.port.input.ReservationResponse import org.springframework.http.ResponseEntity +import org.springframework.util.StringUtils import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.PathVariable import org.springframework.web.bind.annotation.RequestMapping @@ -22,10 +23,18 @@ class GetReservationController( getReservationQuery.loadOneReservationById(UUIDUtils.fromString(reservationId)) @GetMapping - fun getAllReservation(@RequestParam("shopId") shopIdParam: Long?): ResponseEntity> { - val shopId = requireNotNull(shopIdParam) { "가게 식별자는 필수입니다." } + fun getAllReservation(@RequestParam("shopId") shopId: String?): ResponseEntity> { + if (!StringUtils.hasText(shopId)) { + throw IllegalArgumentException("가게 식별자는 필수입니다.") + } return HttpResponseUtils - .mapToResponseEntity(emptiableList = getReservationQuery.loadAllReservationByShopId(shopId)) + .mapToResponseEntity( + emptiableList = getReservationQuery.loadAllReservationByShopId( + UUIDUtils.fromString( + shopId!! + ) + ) + ) } } diff --git a/mealkitary-api/src/main/kotlin/com/mealkitary/reservation/web/request/ReserveProductWebRequest.kt b/mealkitary-api/src/main/kotlin/com/mealkitary/reservation/web/request/ReserveProductWebRequest.kt index af1f35f..f0c54eb 100644 --- a/mealkitary-api/src/main/kotlin/com/mealkitary/reservation/web/request/ReserveProductWebRequest.kt +++ b/mealkitary-api/src/main/kotlin/com/mealkitary/reservation/web/request/ReserveProductWebRequest.kt @@ -1,5 +1,6 @@ package com.mealkitary.reservation.web.request +import com.mealkitary.common.utils.UUIDUtils import com.mealkitary.common.validation.DateValid import com.mealkitary.reservation.application.port.input.ReserveProductRequest import java.time.LocalDateTime @@ -8,7 +9,7 @@ import javax.validation.constraints.NotNull data class ReserveProductWebRequest( @field:NotNull(message = "예약 대상 가게 식별자는 필수입니다.") - val shopId: Long? = null, + val shopId: String? = null, @field:Valid @field:NotNull(message = "예약 상품 목록은 필수입니다.") @@ -21,7 +22,7 @@ data class ReserveProductWebRequest( fun mapToServiceRequest(): ReserveProductRequest { return ReserveProductRequest( - shopId!!, + UUIDUtils.fromString(shopId!!), products!!.map { it.mapToServiceObject() }, LocalDateTime.parse(reservedAt!!) ) diff --git a/mealkitary-api/src/main/kotlin/com/mealkitary/shop/web/GetProductController.kt b/mealkitary-api/src/main/kotlin/com/mealkitary/shop/web/GetProductController.kt index 6ae5f0f..3a655d0 100644 --- a/mealkitary-api/src/main/kotlin/com/mealkitary/shop/web/GetProductController.kt +++ b/mealkitary-api/src/main/kotlin/com/mealkitary/shop/web/GetProductController.kt @@ -1,6 +1,7 @@ package com.mealkitary.shop.web import com.mealkitary.common.utils.HttpResponseUtils +import com.mealkitary.common.utils.UUIDUtils import com.mealkitary.shop.application.port.input.GetProductQuery import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.PathVariable @@ -14,8 +15,8 @@ class GetProductController( ) { @GetMapping("/{shopId}/products") - fun getAllProductOfShop(@PathVariable("shopId") shopId: Long) = + fun getAllProductOfShop(@PathVariable("shopId") shopId: String) = HttpResponseUtils.mapToResponseEntity( - emptiableList = getProductQuery.loadAllProductByShopId(shopId) + emptiableList = getProductQuery.loadAllProductByShopId(UUIDUtils.fromString(shopId)) ) } diff --git a/mealkitary-api/src/main/kotlin/com/mealkitary/shop/web/GetReservableTimeController.kt b/mealkitary-api/src/main/kotlin/com/mealkitary/shop/web/GetReservableTimeController.kt index 8d7f5c3..c195cee 100644 --- a/mealkitary-api/src/main/kotlin/com/mealkitary/shop/web/GetReservableTimeController.kt +++ b/mealkitary-api/src/main/kotlin/com/mealkitary/shop/web/GetReservableTimeController.kt @@ -1,6 +1,7 @@ package com.mealkitary.shop.web import com.mealkitary.common.utils.HttpResponseUtils +import com.mealkitary.common.utils.UUIDUtils import com.mealkitary.shop.application.port.input.GetReservableTimeQuery import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.PathVariable @@ -14,8 +15,8 @@ class GetReservableTimeController( ) { @GetMapping("/{shopId}/reservable-time") - fun getAllReservableTimeOfShop(@PathVariable("shopId") shopId: Long) = + fun getAllReservableTimeOfShop(@PathVariable("shopId") shopId: String) = HttpResponseUtils.mapToResponseEntity( - emptiableList = getReservableTimeQuery.loadAllReservableTimeByShopId(shopId) + emptiableList = getReservableTimeQuery.loadAllReservableTimeByShopId(UUIDUtils.fromString(shopId)) ) } diff --git a/mealkitary-api/src/main/kotlin/com/mealkitary/shop/web/UpdateShopStatusController.kt b/mealkitary-api/src/main/kotlin/com/mealkitary/shop/web/UpdateShopStatusController.kt index aeb88a0..bcfa6b9 100644 --- a/mealkitary-api/src/main/kotlin/com/mealkitary/shop/web/UpdateShopStatusController.kt +++ b/mealkitary-api/src/main/kotlin/com/mealkitary/shop/web/UpdateShopStatusController.kt @@ -1,5 +1,6 @@ package com.mealkitary.shop.web +import com.mealkitary.common.utils.UUIDUtils import com.mealkitary.shop.application.port.input.UpdateShopStatusUseCase import org.springframework.http.ResponseEntity import org.springframework.web.bind.annotation.PathVariable @@ -14,8 +15,8 @@ class UpdateShopStatusController( ) { @PostMapping("/{shopId}/status") - fun updateShopStatus(@PathVariable("shopId") shopId: Long): ResponseEntity { - updateShopStatusUseCase.update(shopId) + fun updateShopStatus(@PathVariable("shopId") shopId: String): ResponseEntity { + updateShopStatusUseCase.update(UUIDUtils.fromString(shopId)) return ResponseEntity.noContent().build() } diff --git a/mealkitary-api/src/test/kotlin/com/docs/reservation/GetReservationControllerDocsTest.kt b/mealkitary-api/src/test/kotlin/com/docs/reservation/GetReservationControllerDocsTest.kt index b3d57d0..3d4d179 100644 --- a/mealkitary-api/src/test/kotlin/com/docs/reservation/GetReservationControllerDocsTest.kt +++ b/mealkitary-api/src/test/kotlin/com/docs/reservation/GetReservationControllerDocsTest.kt @@ -90,10 +90,11 @@ class GetReservationControllerDocsTest : RestDocsSupport() { @Test fun `api docs test - getAllReservation`() { val reservationId = UUID.randomUUID() + val shopId = UUID.randomUUID() val reserveAt = LocalDateTime.of( LocalDate.of(2023, 6, 23), LocalTime.of(6, 30) ) - every { getReservationQuery.loadAllReservationByShopId(1L) } answers { + every { getReservationQuery.loadAllReservationByShopId(shopId) } answers { listOf( ReservationResponse( reservationId, @@ -119,7 +120,7 @@ class GetReservationControllerDocsTest : RestDocsSupport() { ) } - mvc.perform(RestDocumentationRequestBuilders.get("/reservations?shopId=1")) + mvc.perform(RestDocumentationRequestBuilders.get("/reservations?shopId=$shopId")) .andExpect(status().isOk()) .andExpect(content().contentType(MediaType.APPLICATION_JSON)) .andDo( diff --git a/mealkitary-api/src/test/kotlin/com/docs/reservation/ReserveProductControllerDocsTest.kt b/mealkitary-api/src/test/kotlin/com/docs/reservation/ReserveProductControllerDocsTest.kt index b29c4a9..2e97083 100644 --- a/mealkitary-api/src/test/kotlin/com/docs/reservation/ReserveProductControllerDocsTest.kt +++ b/mealkitary-api/src/test/kotlin/com/docs/reservation/ReserveProductControllerDocsTest.kt @@ -32,9 +32,10 @@ class ReserveProductControllerDocsTest : RestDocsSupport() { @Test fun `api docs test - reserveProduct`() { val id = UUID.randomUUID() + val shopId = UUID.randomUUID() every { reserveProductUseCase.reserve(any()) }.answers { id } val reserveProductWebRequest = ReserveProductWebRequest( - 1L, + shopId.toString(), listOf( ReservedWebProduct( 2L, @@ -62,7 +63,7 @@ class ReserveProductControllerDocsTest : RestDocsSupport() { preprocessRequest(prettyPrint()), preprocessResponse(prettyPrint()), requestFields( - fieldWithPath("shopId").type(JsonFieldType.NUMBER).description("예약 대상 가게 식별자"), + fieldWithPath("shopId").type(JsonFieldType.STRING).description("예약 대상 가게 식별자"), fieldWithPath("products.[].productId").type(JsonFieldType.NUMBER).description("예약 대상 상품 식별자"), fieldWithPath("products.[].name").type(JsonFieldType.STRING).description("예약 대상 상품명"), fieldWithPath("products.[].price").type(JsonFieldType.NUMBER).description("예약 대상 상품 가격"), diff --git a/mealkitary-api/src/test/kotlin/com/docs/shop/GetProductControllerDocsTest.kt b/mealkitary-api/src/test/kotlin/com/docs/shop/GetProductControllerDocsTest.kt index 9d46e87..0a4ca7f 100644 --- a/mealkitary-api/src/test/kotlin/com/docs/shop/GetProductControllerDocsTest.kt +++ b/mealkitary-api/src/test/kotlin/com/docs/shop/GetProductControllerDocsTest.kt @@ -19,6 +19,7 @@ import org.springframework.restdocs.request.RequestDocumentation.parameterWithNa import org.springframework.restdocs.request.RequestDocumentation.pathParameters import org.springframework.test.web.servlet.result.MockMvcResultMatchers.content import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status +import java.util.UUID class GetProductControllerDocsTest : RestDocsSupport() { @@ -26,11 +27,12 @@ class GetProductControllerDocsTest : RestDocsSupport() { @Test fun `api docs test - getAllProductOfShopTest`() { - every { getProductQuery.loadAllProductByShopId(1L) }.answers { + val shopId = UUID.randomUUID() + every { getProductQuery.loadAllProductByShopId(shopId) }.answers { listOf(ProductResponse(1L, "부대찌개", 15000)) } - mvc.perform(RestDocumentationRequestBuilders.get("/shops/{shopId}/products", 1)) + mvc.perform(RestDocumentationRequestBuilders.get("/shops/{shopId}/products", shopId)) .andExpect(status().isOk()) .andExpect(content().contentType(MediaType.APPLICATION_JSON)) .andDo( diff --git a/mealkitary-api/src/test/kotlin/com/docs/shop/GetReservableTimeControllerDocsTest.kt b/mealkitary-api/src/test/kotlin/com/docs/shop/GetReservableTimeControllerDocsTest.kt index 0fd2f16..280b1a6 100644 --- a/mealkitary-api/src/test/kotlin/com/docs/shop/GetReservableTimeControllerDocsTest.kt +++ b/mealkitary-api/src/test/kotlin/com/docs/shop/GetReservableTimeControllerDocsTest.kt @@ -19,6 +19,7 @@ import org.springframework.restdocs.request.RequestDocumentation.pathParameters import org.springframework.test.web.servlet.result.MockMvcResultMatchers.content import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status import java.time.LocalTime +import java.util.UUID class GetReservableTimeControllerDocsTest : RestDocsSupport() { @@ -26,11 +27,12 @@ class GetReservableTimeControllerDocsTest : RestDocsSupport() { @Test fun `api docs test - getAllReservableTimeOfShopTest`() { - every { getReservableTimeQuery.loadAllReservableTimeByShopId(1L) }.answers { + val shopId = UUID.randomUUID() + every { getReservableTimeQuery.loadAllReservableTimeByShopId(shopId) }.answers { listOf(LocalTime.of(6, 30)) } - mvc.perform(RestDocumentationRequestBuilders.get("/shops/{shopId}/reservable-time", 1)) + mvc.perform(RestDocumentationRequestBuilders.get("/shops/{shopId}/reservable-time", shopId)) .andExpect(status().isOk()) .andExpect(content().contentType(MediaType.APPLICATION_JSON)) .andDo( diff --git a/mealkitary-api/src/test/kotlin/com/docs/shop/GetShopControllerDocsTest.kt b/mealkitary-api/src/test/kotlin/com/docs/shop/GetShopControllerDocsTest.kt index b7c13b7..be9a4fc 100644 --- a/mealkitary-api/src/test/kotlin/com/docs/shop/GetShopControllerDocsTest.kt +++ b/mealkitary-api/src/test/kotlin/com/docs/shop/GetShopControllerDocsTest.kt @@ -17,6 +17,7 @@ import org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath import org.springframework.restdocs.payload.PayloadDocumentation.responseFields import org.springframework.test.web.servlet.result.MockMvcResultMatchers.content import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status +import java.util.UUID class GetShopControllerDocsTest : RestDocsSupport() { @@ -24,8 +25,9 @@ class GetShopControllerDocsTest : RestDocsSupport() { @Test fun `api docs test - getAllShopTest`() { + val shopId = UUID.randomUUID() every { getShopQuery.loadAllShop() }.answers { - listOf(ShopResponse(1L, "집밥뚝딱")) + listOf(ShopResponse(shopId, "집밥뚝딱")) } mvc.perform(RestDocumentationRequestBuilders.get("/shops/")) @@ -38,7 +40,7 @@ class GetShopControllerDocsTest : RestDocsSupport() { preprocessResponse(prettyPrint()), responseFields( fieldWithPath("[]").type(JsonFieldType.ARRAY).description("가게 목록 배열"), - fieldWithPath("[].id").type(JsonFieldType.NUMBER).description("가게 식별자"), + fieldWithPath("[].id").type(JsonFieldType.STRING).description("가게 식별자"), fieldWithPath("[].title").type(JsonFieldType.STRING).description("가게명") ) ) diff --git a/mealkitary-api/src/test/kotlin/com/docs/shop/RegisterShopControllerDocsTest.kt b/mealkitary-api/src/test/kotlin/com/docs/shop/RegisterShopControllerDocsTest.kt index c00ef51..5a4fea7 100644 --- a/mealkitary-api/src/test/kotlin/com/docs/shop/RegisterShopControllerDocsTest.kt +++ b/mealkitary-api/src/test/kotlin/com/docs/shop/RegisterShopControllerDocsTest.kt @@ -19,6 +19,7 @@ import org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath import org.springframework.restdocs.payload.PayloadDocumentation.requestFields import org.springframework.test.web.servlet.result.MockMvcResultMatchers.header import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status +import java.util.UUID class RegisterShopControllerDocsTest : RestDocsSupport() { @@ -26,7 +27,8 @@ class RegisterShopControllerDocsTest : RestDocsSupport() { @Test fun `api docs test - registerShop`() { - every { registerShopUseCase.register(any()) } answers { 1L } + val shopId = UUID.randomUUID() + every { registerShopUseCase.register(any()) } answers { shopId } val registerShopWebRequest = RegisterShopWebRequest("집밥뚝딱 안양점", "123-23-12345", "경기도 안양시 동안구 벌말로") @@ -36,7 +38,7 @@ class RegisterShopControllerDocsTest : RestDocsSupport() { .content(objectMapper.writeValueAsString(registerShopWebRequest)) ) .andExpect(status().isCreated) - .andExpect(header().string("Location", "http://localhost/shops/1")) + .andExpect(header().string("Location", "http://localhost/shops/$shopId")) .andDo( MockMvcRestDocumentation.document( "shop-post", diff --git a/mealkitary-api/src/test/kotlin/com/docs/shop/UpdateShopStatusControllerDocsTest.kt b/mealkitary-api/src/test/kotlin/com/docs/shop/UpdateShopStatusControllerDocsTest.kt index 7a573ba..0e33aab 100644 --- a/mealkitary-api/src/test/kotlin/com/docs/shop/UpdateShopStatusControllerDocsTest.kt +++ b/mealkitary-api/src/test/kotlin/com/docs/shop/UpdateShopStatusControllerDocsTest.kt @@ -14,6 +14,7 @@ import org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPri import org.springframework.restdocs.request.RequestDocumentation.parameterWithName import org.springframework.restdocs.request.RequestDocumentation.pathParameters import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status +import java.util.UUID class UpdateShopStatusControllerDocsTest : RestDocsSupport() { @@ -21,7 +22,7 @@ class UpdateShopStatusControllerDocsTest : RestDocsSupport() { @Test fun `api docs test - updateShopStatus`() { - val shopId = 1L + val shopId = UUID.randomUUID() every { updateShopStatsUseCase.update(shopId) }.answers { } mvc.perform( diff --git a/mealkitary-api/src/test/kotlin/com/mealkitary/reservation/web/GetReservationControllerTest.kt b/mealkitary-api/src/test/kotlin/com/mealkitary/reservation/web/GetReservationControllerTest.kt index 07a4182..54a5b35 100644 --- a/mealkitary-api/src/test/kotlin/com/mealkitary/reservation/web/GetReservationControllerTest.kt +++ b/mealkitary-api/src/test/kotlin/com/mealkitary/reservation/web/GetReservationControllerTest.kt @@ -69,10 +69,11 @@ class GetReservationControllerTest : WebIntegrationTestSupport() { @Test fun `api integration test - getAllReservation`() { val reservationId = UUID.randomUUID() + val shopId = UUID.randomUUID() val reserveAt = LocalDateTime.of( LocalDate.of(2023, 6, 23), LocalTime.of(6, 30) ) - every { getReservationQuery.loadAllReservationByShopId(1L) } answers { + every { getReservationQuery.loadAllReservationByShopId(any()) } answers { listOf( ReservationResponse( reservationId, @@ -98,7 +99,7 @@ class GetReservationControllerTest : WebIntegrationTestSupport() { ) } - mvc.perform(get("/reservations?shopId=1")) + mvc.perform(get("/reservations?shopId=$shopId")) .andExpect(status().isOk()) .andExpect(content().contentType(MediaType.APPLICATION_JSON)) .andExpect(jsonPath("$.[0].reservationId").value(reservationId.toString())) @@ -133,7 +134,7 @@ class GetReservationControllerTest : WebIntegrationTestSupport() { fun `api integration test - getAllReservation - 해당 가게의 예약이 존재하지 않으면 204 NoContent를 반환한다`() { every { getReservationQuery.loadAllReservationByShopId(any()) } answers { emptyList() } - mvc.perform(get("/reservations?shopId=1")) + mvc.perform(get("/reservations?shopId=${UUID.randomUUID()}")) .andExpect(status().isNoContent()) } @@ -147,6 +148,16 @@ class GetReservationControllerTest : WebIntegrationTestSupport() { .andExpect(jsonPath("$.message").value("잘못된 UUID 형식입니다.")) } + @Test + fun `api integration test - 가게 식별자가 UUID 형태가 아니라면 400 에러를 발생한다`() { + mvc.perform( + get("/reservations?shopId=invalid-uuid-test") + ) + .andExpect(status().isBadRequest) + .andExpect(jsonPath("$.status").value("400")) + .andExpect(jsonPath("$.message").value("잘못된 UUID 형식입니다.")) + } + @Test fun `api integration test - getOneReservation - 내부에서 EntityNotFound 에러가 발생하면 404 에러를 발생한다`() { every { getReservationQuery.loadOneReservationById(any()) } diff --git a/mealkitary-api/src/test/kotlin/com/mealkitary/reservation/web/ReserveProductControllerTest.kt b/mealkitary-api/src/test/kotlin/com/mealkitary/reservation/web/ReserveProductControllerTest.kt index 47d3568..ce60c30 100644 --- a/mealkitary-api/src/test/kotlin/com/mealkitary/reservation/web/ReserveProductControllerTest.kt +++ b/mealkitary-api/src/test/kotlin/com/mealkitary/reservation/web/ReserveProductControllerTest.kt @@ -20,11 +20,12 @@ class ReserveProductControllerTest : WebIntegrationTestSupport() { @Test fun `api integration test - reserveProduct`() { val id = UUID.randomUUID() + val shopId = UUID.randomUUID() every { reserveProductUseCase.reserve(any()) }.answers { id } val reserveProductWebRequest = ReserveProductWebRequest( - 1L, + shopId.toString(), listOf( ReservedWebProduct( 2L, @@ -80,7 +81,7 @@ class ReserveProductControllerTest : WebIntegrationTestSupport() { @Test fun `api integration test - 예약 시간이 누락된 경우 400 에러를 발생한다`() { val reserveProductWebRequest = ReserveProductWebRequest( - shopId = 2, + shopId = UUID.randomUUID().toString(), products = listOf( ReservedWebProduct( 2L, @@ -111,7 +112,7 @@ class ReserveProductControllerTest : WebIntegrationTestSupport() { @Test fun `api integration test - 예약 상품 목록이 누락된 경우 400 에러를 발생한다`() { val reserveProductWebRequest = ReserveProductWebRequest( - shopId = 2, + shopId = UUID.randomUUID().toString(), reservedAt = LocalDateTime.of( LocalDate.now().plusDays(1), LocalTime.of(16, 0) @@ -142,12 +143,40 @@ class ReserveProductControllerTest : WebIntegrationTestSupport() { .andExpect(jsonPath("$.message").value("JSON 형식이 잘못되었습니다.")) } + @Test + fun `api integration test - 가게 식별자가 UUID 형태가 아니라면 400 에러를 발생한다`() { + val reserveProductWebRequest = ReserveProductWebRequest( + shopId = "invalid-uuid-test", + products = listOf( + ReservedWebProduct( + 2L, + "부대찌개", + 3000, + 3 + ) + ), + reservedAt = LocalDateTime.of( + LocalDate.now().plusDays(1), + LocalTime.of(16, 0) + ).toString() + ) + + mvc.perform( + post("/reservations") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(reserveProductWebRequest)) + ) + .andExpect(status().isBadRequest) + .andExpect(jsonPath("$.status").value("400")) + .andExpect(jsonPath("$.message").value("잘못된 UUID 형식입니다.")) + } + @Test fun `api integration test - 예약 대상 가게가 존재하지 않는 경우 404 에러를 발생한다`() { every { reserveProductUseCase.reserve(any()) } .throws(EntityNotFoundException("존재하지 않는 가게입니다.")) val reserveProductWebRequest = ReserveProductWebRequest( - 1L, + UUID.randomUUID().toString(), listOf( ReservedWebProduct( 2L, diff --git a/mealkitary-api/src/test/kotlin/com/mealkitary/shop/web/GetProductControllerTest.kt b/mealkitary-api/src/test/kotlin/com/mealkitary/shop/web/GetProductControllerTest.kt index f12ebcc..3c60c1a 100644 --- a/mealkitary-api/src/test/kotlin/com/mealkitary/shop/web/GetProductControllerTest.kt +++ b/mealkitary-api/src/test/kotlin/com/mealkitary/shop/web/GetProductControllerTest.kt @@ -10,31 +10,34 @@ import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get import org.springframework.test.web.servlet.result.MockMvcResultMatchers.content import org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status +import java.util.UUID class GetProductControllerTest : WebIntegrationTestSupport() { @Test fun `api integration test - getAllProductOfShopTest`() { - every { getProductQuery.loadAllProductByShopId(1L) }.answers { + val shopId = UUID.randomUUID() + every { getProductQuery.loadAllProductByShopId(shopId) }.answers { listOf(ProductResponse(1L, "부대찌개", 15000)) } - mvc.perform(get("/shops/{shopId}/products", 1)) + mvc.perform(get("/shops/{shopId}/products", shopId)) .andExpect(status().isOk()) .andExpect(content().contentType(MediaType.APPLICATION_JSON)) .andExpect(jsonPath("$.[0].id").value(1)) .andExpect(jsonPath("$.[0].name").value("부대찌개")) .andExpect(jsonPath("$.[0].price").value(15000)) - verify { getProductQuery.loadAllProductByShopId(1L) } + verify { getProductQuery.loadAllProductByShopId(shopId) } } @Test fun `api integration test - 존재하지 않는 가게의 상품 조회 시 404 에러를 발생한다`() { - every { getProductQuery.loadAllProductByShopId(1L) } + val shopId = UUID.randomUUID() + every { getProductQuery.loadAllProductByShopId(shopId) } .throws(EntityNotFoundException("존재하지 않는 가게입니다.")) - mvc.perform(get("/shops/{shopId}/products", 1)) + mvc.perform(get("/shops/{shopId}/products", shopId)) .andExpect(status().isNotFound()) .andExpect(content().contentType(MediaType.APPLICATION_JSON)) .andExpect(jsonPath("$.status").value(404)) @@ -43,9 +46,20 @@ class GetProductControllerTest : WebIntegrationTestSupport() { @Test fun `api integration test - 가게의 상품이 존재하지 않는다면 204 NoContent를 반환한다`() { - every { getProductQuery.loadAllProductByShopId(1L) } answers { emptyList() } + val shopId = UUID.randomUUID() + every { getProductQuery.loadAllProductByShopId(shopId) } answers { emptyList() } - mvc.perform(get("/shops/{shopId}/products", 1)) + mvc.perform(get("/shops/{shopId}/products", shopId)) .andExpect(status().isNoContent()) } + + @Test + fun `api integration test - 가게 식별자가 UUID 형태가 아니라면 400 에러를 발생한다`() { + mvc.perform( + get("/shops/{shopId}/products", "invalid-uuid-test") + ) + .andExpect(status().isBadRequest) + .andExpect(jsonPath("$.status").value("400")) + .andExpect(jsonPath("$.message").value("잘못된 UUID 형식입니다.")) + } } diff --git a/mealkitary-api/src/test/kotlin/com/mealkitary/shop/web/GetReservableTimeControllerTest.kt b/mealkitary-api/src/test/kotlin/com/mealkitary/shop/web/GetReservableTimeControllerTest.kt index 26702ac..afad765 100644 --- a/mealkitary-api/src/test/kotlin/com/mealkitary/shop/web/GetReservableTimeControllerTest.kt +++ b/mealkitary-api/src/test/kotlin/com/mealkitary/shop/web/GetReservableTimeControllerTest.kt @@ -10,29 +10,32 @@ import org.springframework.test.web.servlet.result.MockMvcResultMatchers.content import org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status import java.time.LocalTime +import java.util.UUID class GetReservableTimeControllerTest : WebIntegrationTestSupport() { @Test fun `api integration test - getAllReservableTimeOfShopTest`() { - every { getReservableTimeQuery.loadAllReservableTimeByShopId(1L) }.answers { + val shopId = UUID.randomUUID() + every { getReservableTimeQuery.loadAllReservableTimeByShopId(shopId) }.answers { listOf(LocalTime.of(6, 30)) } - mvc.perform(MockMvcRequestBuilders.get("/shops/{shopId}/reservable-time", 1)) + mvc.perform(MockMvcRequestBuilders.get("/shops/{shopId}/reservable-time", shopId)) .andExpect(status().isOk()) .andExpect(content().contentType(MediaType.APPLICATION_JSON)) .andExpect(jsonPath("$.[0]").value("06:30:00")) - verify { getReservableTimeQuery.loadAllReservableTimeByShopId(1L) } + verify { getReservableTimeQuery.loadAllReservableTimeByShopId(shopId) } } @Test fun `api integration test - 존재하지 않는 가게의 예약 가능 시간 조회 시 404 에러를 발생한다`() { - every { getReservableTimeQuery.loadAllReservableTimeByShopId(1L) } + val shopId = UUID.randomUUID() + every { getReservableTimeQuery.loadAllReservableTimeByShopId(shopId) } .throws(EntityNotFoundException("존재하지 않는 가게입니다.")) - mvc.perform(MockMvcRequestBuilders.get("/shops/{shopId}/reservable-time", 1)) + mvc.perform(MockMvcRequestBuilders.get("/shops/{shopId}/reservable-time", shopId)) .andExpect(status().isNotFound()) .andExpect(content().contentType(MediaType.APPLICATION_JSON)) .andExpect(jsonPath("$.status").value(404)) @@ -41,9 +44,20 @@ class GetReservableTimeControllerTest : WebIntegrationTestSupport() { @Test fun `api integration test - 가게의 예약 가능 시간이 존재하지 않는다면 204 NoContent를 반환한다`() { - every { getReservableTimeQuery.loadAllReservableTimeByShopId(1L) }.answers { emptyList() } + val shopId = UUID.randomUUID() + every { getReservableTimeQuery.loadAllReservableTimeByShopId(shopId) }.answers { emptyList() } - mvc.perform(MockMvcRequestBuilders.get("/shops/{shopId}/reservable-time", 1)) + mvc.perform(MockMvcRequestBuilders.get("/shops/{shopId}/reservable-time", shopId)) .andExpect(status().isNoContent()) } + + @Test + fun `api integration test - 가게 식별자가 UUID 형태가 아니라면 400 에러를 발생한다`() { + mvc.perform( + MockMvcRequestBuilders.get("/shops/{shopId}/reservable-time", "invalid-uuid-test") + ) + .andExpect(status().isBadRequest) + .andExpect(jsonPath("$.status").value("400")) + .andExpect(jsonPath("$.message").value("잘못된 UUID 형식입니다.")) + } } diff --git a/mealkitary-api/src/test/kotlin/com/mealkitary/shop/web/GetShopControllerTest.kt b/mealkitary-api/src/test/kotlin/com/mealkitary/shop/web/GetShopControllerTest.kt index 3ddc8e7..f15f440 100644 --- a/mealkitary-api/src/test/kotlin/com/mealkitary/shop/web/GetShopControllerTest.kt +++ b/mealkitary-api/src/test/kotlin/com/mealkitary/shop/web/GetShopControllerTest.kt @@ -8,19 +8,21 @@ import org.springframework.test.web.servlet.request.MockMvcRequestBuilders import org.springframework.test.web.servlet.result.MockMvcResultMatchers.content import org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status +import java.util.UUID class GetShopControllerTest : WebIntegrationTestSupport() { @Test fun `api integration test - getAllShopTest`() { + val shopId = UUID.randomUUID() every { getShopQuery.loadAllShop() }.answers { - listOf(ShopResponse(1L, "집밥뚝딱")) + listOf(ShopResponse(shopId, "집밥뚝딱")) } mvc.perform(MockMvcRequestBuilders.get("/shops/")) .andExpect(status().isOk()) .andExpect(content().contentType(MediaType.APPLICATION_JSON)) - .andExpect(jsonPath("$.[0].id").value(1)) + .andExpect(jsonPath("$.[0].id").value(shopId.toString())) .andExpect(jsonPath("$.[0].title").value("집밥뚝딱")) } diff --git a/mealkitary-api/src/test/kotlin/com/mealkitary/shop/web/RegisterShopControllerTest.kt b/mealkitary-api/src/test/kotlin/com/mealkitary/shop/web/RegisterShopControllerTest.kt index 521da7c..3f02eee 100644 --- a/mealkitary-api/src/test/kotlin/com/mealkitary/shop/web/RegisterShopControllerTest.kt +++ b/mealkitary-api/src/test/kotlin/com/mealkitary/shop/web/RegisterShopControllerTest.kt @@ -8,12 +8,14 @@ import org.springframework.test.web.servlet.request.MockMvcRequestBuilders import org.springframework.test.web.servlet.result.MockMvcResultMatchers.header import org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status +import java.util.UUID class RegisterShopControllerTest : WebIntegrationTestSupport() { @Test fun `api integration test - registerShop`() { - every { registerShopUseCase.register(any()) } answers { 1L } + val shopId = UUID.randomUUID() + every { registerShopUseCase.register(any()) } answers { shopId } val registerShopWebRequest = RegisterShopWebRequest("집밥뚝딱 안양점", "123-23-12345", "경기도 안양시 동안구 벌말로 40") @@ -23,7 +25,7 @@ class RegisterShopControllerTest : WebIntegrationTestSupport() { .content(objectMapper.writeValueAsString(registerShopWebRequest)) ) .andExpect(status().isCreated) - .andExpect(header().string("Location", "http://localhost/shops/1")) + .andExpect(header().string("Location", "http://localhost/shops/$shopId")) } @Test diff --git a/mealkitary-api/src/test/kotlin/com/mealkitary/shop/web/UpdateShopStatusControllerTest.kt b/mealkitary-api/src/test/kotlin/com/mealkitary/shop/web/UpdateShopStatusControllerTest.kt index 6f39494..cd10011 100644 --- a/mealkitary-api/src/test/kotlin/com/mealkitary/shop/web/UpdateShopStatusControllerTest.kt +++ b/mealkitary-api/src/test/kotlin/com/mealkitary/shop/web/UpdateShopStatusControllerTest.kt @@ -2,19 +2,31 @@ package com.mealkitary.shop.web import com.mealkitary.WebIntegrationTestSupport import io.mockk.every -import org.springframework.test.web.servlet.request.MockMvcRequestBuilders -import org.springframework.test.web.servlet.result.MockMvcResultMatchers +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post +import org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath +import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status +import java.util.UUID class UpdateShopStatusControllerTest : WebIntegrationTestSupport() { @Test fun `api integration test - updateShopStatus`() { - val shopId = 1L + val shopId = UUID.randomUUID() every { updateShopStatusUseCase.update(any()) } answers {} mvc.perform( - MockMvcRequestBuilders.post("/shops/{shopId}/status", shopId) + post("/shops/{shopId}/status", shopId) ) - .andExpect(MockMvcResultMatchers.status().isNoContent) + .andExpect(status().isNoContent) + } + + @Test + fun `api integration test - 가게 식별자가 UUID 형태가 아니라면 400 에러를 발생한다`() { + mvc.perform( + post("/shops/{shopId}/status", "invalid-uuid-test") + ) + .andExpect(status().isBadRequest) + .andExpect(jsonPath("$.status").value("400")) + .andExpect(jsonPath("$.message").value("잘못된 UUID 형식입니다.")) } } diff --git a/mealkitary-application/src/main/kotlin/com/mealkitary/reservation/application/port/input/GetReservationQuery.kt b/mealkitary-application/src/main/kotlin/com/mealkitary/reservation/application/port/input/GetReservationQuery.kt index 57c3884..fa5090c 100644 --- a/mealkitary-application/src/main/kotlin/com/mealkitary/reservation/application/port/input/GetReservationQuery.kt +++ b/mealkitary-application/src/main/kotlin/com/mealkitary/reservation/application/port/input/GetReservationQuery.kt @@ -6,5 +6,5 @@ interface GetReservationQuery { fun loadOneReservationById(reservationId: UUID): ReservationResponse - fun loadAllReservationByShopId(shopId: Long): List + fun loadAllReservationByShopId(shopId: UUID): List } diff --git a/mealkitary-application/src/main/kotlin/com/mealkitary/reservation/application/port/input/ReserveProductRequest.kt b/mealkitary-application/src/main/kotlin/com/mealkitary/reservation/application/port/input/ReserveProductRequest.kt index 7f4522d..e0148ff 100644 --- a/mealkitary-application/src/main/kotlin/com/mealkitary/reservation/application/port/input/ReserveProductRequest.kt +++ b/mealkitary-application/src/main/kotlin/com/mealkitary/reservation/application/port/input/ReserveProductRequest.kt @@ -1,9 +1,10 @@ package com.mealkitary.reservation.application.port.input import java.time.LocalDateTime +import java.util.UUID data class ReserveProductRequest( - val shopId: Long, + val shopId: UUID, val products: List, val reservedAt: LocalDateTime ) diff --git a/mealkitary-application/src/main/kotlin/com/mealkitary/reservation/application/port/output/LoadReservationPort.kt b/mealkitary-application/src/main/kotlin/com/mealkitary/reservation/application/port/output/LoadReservationPort.kt index 84b3993..06b7a84 100644 --- a/mealkitary-application/src/main/kotlin/com/mealkitary/reservation/application/port/output/LoadReservationPort.kt +++ b/mealkitary-application/src/main/kotlin/com/mealkitary/reservation/application/port/output/LoadReservationPort.kt @@ -10,5 +10,5 @@ interface LoadReservationPort { fun queryOneReservationById(reservationId: UUID): ReservationResponse - fun queryAllReservationByShopId(shopId: Long): List + fun queryAllReservationByShopId(shopId: UUID): List } diff --git a/mealkitary-application/src/main/kotlin/com/mealkitary/reservation/application/service/GetReservationService.kt b/mealkitary-application/src/main/kotlin/com/mealkitary/reservation/application/service/GetReservationService.kt index 84f19d0..45a0714 100644 --- a/mealkitary-application/src/main/kotlin/com/mealkitary/reservation/application/service/GetReservationService.kt +++ b/mealkitary-application/src/main/kotlin/com/mealkitary/reservation/application/service/GetReservationService.kt @@ -16,6 +16,6 @@ class GetReservationService( override fun loadOneReservationById(reservationId: UUID) = loadReservationPort.queryOneReservationById(reservationId) - override fun loadAllReservationByShopId(shopId: Long): List = + override fun loadAllReservationByShopId(shopId: UUID): List = loadReservationPort.queryAllReservationByShopId(shopId) } diff --git a/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/port/input/GetProductQuery.kt b/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/port/input/GetProductQuery.kt index 5e6c150..c03e93e 100644 --- a/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/port/input/GetProductQuery.kt +++ b/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/port/input/GetProductQuery.kt @@ -1,6 +1,8 @@ package com.mealkitary.shop.application.port.input +import java.util.UUID + interface GetProductQuery { - fun loadAllProductByShopId(shopId: Long): List + fun loadAllProductByShopId(shopId: UUID): List } diff --git a/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/port/input/GetReservableTimeQuery.kt b/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/port/input/GetReservableTimeQuery.kt index 039e9a8..d4152df 100644 --- a/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/port/input/GetReservableTimeQuery.kt +++ b/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/port/input/GetReservableTimeQuery.kt @@ -1,8 +1,9 @@ package com.mealkitary.shop.application.port.input import java.time.LocalTime +import java.util.UUID interface GetReservableTimeQuery { - fun loadAllReservableTimeByShopId(shopId: Long): List + fun loadAllReservableTimeByShopId(shopId: UUID): List } diff --git a/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/port/input/RegisterShopUseCase.kt b/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/port/input/RegisterShopUseCase.kt index fcc5ba8..29822db 100644 --- a/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/port/input/RegisterShopUseCase.kt +++ b/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/port/input/RegisterShopUseCase.kt @@ -1,6 +1,8 @@ package com.mealkitary.shop.application.port.input +import java.util.UUID + interface RegisterShopUseCase { - fun register(registerShopRequest: RegisterShopRequest): Long + fun register(registerShopRequest: RegisterShopRequest): UUID } diff --git a/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/port/input/ShopResponse.kt b/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/port/input/ShopResponse.kt index 9054f9e..4d9fcc5 100644 --- a/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/port/input/ShopResponse.kt +++ b/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/port/input/ShopResponse.kt @@ -1,3 +1,5 @@ package com.mealkitary.shop.application.port.input -data class ShopResponse(val id: Long?, val title: String) +import java.util.UUID + +data class ShopResponse(val id: UUID, val title: String) diff --git a/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/port/input/UpdateShopStatusUseCase.kt b/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/port/input/UpdateShopStatusUseCase.kt index c65e600..e24ba47 100644 --- a/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/port/input/UpdateShopStatusUseCase.kt +++ b/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/port/input/UpdateShopStatusUseCase.kt @@ -1,6 +1,8 @@ package com.mealkitary.shop.application.port.input +import java.util.UUID + interface UpdateShopStatusUseCase { - fun update(shopId: Long) + fun update(shopId: UUID) } diff --git a/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/port/output/CheckExistenceShopPort.kt b/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/port/output/CheckExistenceShopPort.kt index 7630295..6e4ecfe 100644 --- a/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/port/output/CheckExistenceShopPort.kt +++ b/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/port/output/CheckExistenceShopPort.kt @@ -1,6 +1,8 @@ package com.mealkitary.shop.application.port.output +import java.util.UUID + interface CheckExistenceShopPort { - fun hasReservations(shopId: Long): Boolean + fun hasReservations(shopId: UUID): Boolean } diff --git a/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/port/output/LoadProductPort.kt b/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/port/output/LoadProductPort.kt index e121236..41ec3e3 100644 --- a/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/port/output/LoadProductPort.kt +++ b/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/port/output/LoadProductPort.kt @@ -1,8 +1,9 @@ package com.mealkitary.shop.application.port.output import com.mealkitary.shop.domain.product.Product +import java.util.UUID interface LoadProductPort { - fun loadAllProductByShopId(shopId: Long): List + fun loadAllProductByShopId(shopId: UUID): List } diff --git a/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/port/output/LoadReservableTimePort.kt b/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/port/output/LoadReservableTimePort.kt index bebd866..3483984 100644 --- a/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/port/output/LoadReservableTimePort.kt +++ b/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/port/output/LoadReservableTimePort.kt @@ -1,8 +1,9 @@ package com.mealkitary.shop.application.port.output import java.time.LocalTime +import java.util.UUID interface LoadReservableTimePort { - fun loadAllReservableTimeByShopId(shopId: Long): List + fun loadAllReservableTimeByShopId(shopId: UUID): List } diff --git a/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/port/output/LoadShopPort.kt b/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/port/output/LoadShopPort.kt index 71db4ae..4d52539 100644 --- a/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/port/output/LoadShopPort.kt +++ b/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/port/output/LoadShopPort.kt @@ -1,9 +1,10 @@ package com.mealkitary.shop.application.port.output import com.mealkitary.shop.domain.shop.Shop +import java.util.UUID interface LoadShopPort { fun loadAllShop(): List - fun loadOneShopById(shopId: Long): Shop + fun loadOneShopById(shopId: UUID): Shop } diff --git a/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/port/output/SaveShopPort.kt b/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/port/output/SaveShopPort.kt index eda5b38..e56cc80 100644 --- a/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/port/output/SaveShopPort.kt +++ b/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/port/output/SaveShopPort.kt @@ -1,8 +1,9 @@ package com.mealkitary.shop.application.port.output import com.mealkitary.shop.domain.shop.Shop +import java.util.UUID interface SaveShopPort { - fun saveOne(shop: Shop): Long + fun saveOne(shop: Shop): UUID } diff --git a/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/service/GetProductService.kt b/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/service/GetProductService.kt index 0703ace..c4078e1 100644 --- a/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/service/GetProductService.kt +++ b/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/service/GetProductService.kt @@ -5,6 +5,7 @@ import com.mealkitary.shop.application.port.input.ProductResponse import com.mealkitary.shop.application.port.output.LoadProductPort import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional +import java.util.UUID @Service @Transactional(readOnly = true) @@ -12,6 +13,6 @@ class GetProductService( private val loadProductPort: LoadProductPort ) : GetProductQuery { - override fun loadAllProductByShopId(shopId: Long) = loadProductPort.loadAllProductByShopId(shopId) + override fun loadAllProductByShopId(shopId: UUID) = loadProductPort.loadAllProductByShopId(shopId) .map { ProductResponse(it.id.id, it.name, it.price.value) } } diff --git a/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/service/GetReservableTimeService.kt b/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/service/GetReservableTimeService.kt index 2bd14f5..5826fa2 100644 --- a/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/service/GetReservableTimeService.kt +++ b/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/service/GetReservableTimeService.kt @@ -4,6 +4,7 @@ import com.mealkitary.shop.application.port.input.GetReservableTimeQuery import com.mealkitary.shop.application.port.output.LoadReservableTimePort import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional +import java.util.UUID @Service @Transactional(readOnly = true) @@ -11,6 +12,6 @@ class GetReservableTimeService( private val loadReservableTimePort: LoadReservableTimePort ) : GetReservableTimeQuery { - override fun loadAllReservableTimeByShopId(shopId: Long) = + override fun loadAllReservableTimeByShopId(shopId: UUID) = loadReservableTimePort.loadAllReservableTimeByShopId(shopId) } diff --git a/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/service/RegisterShopService.kt b/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/service/RegisterShopService.kt index f36d12c..c0ea848 100644 --- a/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/service/RegisterShopService.kt +++ b/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/service/RegisterShopService.kt @@ -6,6 +6,7 @@ import com.mealkitary.shop.application.port.output.SaveShopPort import com.mealkitary.shop.domain.shop.factory.ShopFactory import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional +import java.util.UUID @Service @Transactional @@ -14,7 +15,7 @@ class RegisterShopService( private val shopFactory: ShopFactory ) : RegisterShopUseCase { - override fun register(registerShopRequest: RegisterShopRequest): Long { + override fun register(registerShopRequest: RegisterShopRequest): UUID { val shop = shopFactory.createOne( registerShopRequest.title, registerShopRequest.brn, diff --git a/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/service/UpdateShopStatusService.kt b/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/service/UpdateShopStatusService.kt index 3893e0c..fd70abb 100644 --- a/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/service/UpdateShopStatusService.kt +++ b/mealkitary-application/src/main/kotlin/com/mealkitary/shop/application/service/UpdateShopStatusService.kt @@ -6,6 +6,7 @@ import com.mealkitary.shop.application.port.output.LoadShopPort import com.mealkitary.shop.domain.shop.Shop import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional +import java.util.UUID @Service @Transactional @@ -14,7 +15,7 @@ class UpdateShopStatusService( private val loadShopPort: LoadShopPort ) : UpdateShopStatusUseCase { - override fun update(shopId: Long) { + override fun update(shopId: UUID) { val shop = loadShopPort.loadOneShopById(shopId) if (shop.status.isValidStatus()) { @@ -23,7 +24,7 @@ class UpdateShopStatusService( updateStatus(shop) } - private fun checkReservationByShopId(shopId: Long) { + private fun checkReservationByShopId(shopId: UUID) { if (checkExistenceShopPort.hasReservations(shopId)) { throw IllegalStateException("예약이 존재할 경우 가게 상태를 INVALID로 변경할 수 없습니다.") } diff --git a/mealkitary-application/src/test/kotlin/com/mealkitary/reservation/application/service/GetReservationServiceTest.kt b/mealkitary-application/src/test/kotlin/com/mealkitary/reservation/application/service/GetReservationServiceTest.kt index 080e552..e802edf 100644 --- a/mealkitary-application/src/test/kotlin/com/mealkitary/reservation/application/service/GetReservationServiceTest.kt +++ b/mealkitary-application/src/test/kotlin/com/mealkitary/reservation/application/service/GetReservationServiceTest.kt @@ -61,7 +61,7 @@ class GetReservationServiceTest : AnnotationSpec() { ) } - val result = getReservationService.loadAllReservationByShopId(1L) + val result = getReservationService.loadAllReservationByShopId(UUID.randomUUID()) val resultReservation = result.get(0) result.size shouldBe 2 diff --git a/mealkitary-application/src/test/kotlin/com/mealkitary/reservation/application/service/ReserveProductServiceTest.kt b/mealkitary-application/src/test/kotlin/com/mealkitary/reservation/application/service/ReserveProductServiceTest.kt index be669a5..6c0fce9 100644 --- a/mealkitary-application/src/test/kotlin/com/mealkitary/reservation/application/service/ReserveProductServiceTest.kt +++ b/mealkitary-application/src/test/kotlin/com/mealkitary/reservation/application/service/ReserveProductServiceTest.kt @@ -107,7 +107,7 @@ class ReserveProductServiceTest : AnnotationSpec() { } private fun givenInvalidShop() { - every { loadShopPort.loadOneShopById(1L) } answers { + every { loadShopPort.loadOneShopById(any()) } answers { ShopTestData.defaultShop() .withStatus(ShopStatus.INVALID) .build() @@ -115,7 +115,7 @@ class ReserveProductServiceTest : AnnotationSpec() { } private fun givenShop() { - every { loadShopPort.loadOneShopById(1L) } answers { + every { loadShopPort.loadOneShopById(any()) } answers { ShopTestData.defaultShop() .withReservableTimes( LocalTime.of(16, 0) @@ -132,7 +132,6 @@ class ReserveProductServiceTest : AnnotationSpec() { } private fun createReserveProductRequest( - shopId: Long = 1L, reservedProducts: List = listOf( ReservedProduct( 2L, @@ -146,7 +145,7 @@ class ReserveProductServiceTest : AnnotationSpec() { LocalTime.of(16, 0) ) ) = ReserveProductRequest( - shopId, + UUID.randomUUID(), reservedProducts, reservedAt ) diff --git a/mealkitary-application/src/test/kotlin/com/mealkitary/shop/application/service/GetProductServiceTest.kt b/mealkitary-application/src/test/kotlin/com/mealkitary/shop/application/service/GetProductServiceTest.kt index b0b8f8e..8f5ac23 100644 --- a/mealkitary-application/src/test/kotlin/com/mealkitary/shop/application/service/GetProductServiceTest.kt +++ b/mealkitary-application/src/test/kotlin/com/mealkitary/shop/application/service/GetProductServiceTest.kt @@ -9,6 +9,7 @@ import io.kotest.core.spec.style.AnnotationSpec import io.kotest.matchers.shouldBe import io.mockk.every import io.mockk.mockk +import java.util.UUID class GetProductServiceTest : AnnotationSpec() { @@ -17,12 +18,12 @@ class GetProductServiceTest : AnnotationSpec() { @Test fun `service unit test - 가게 ID에 해당하는 가게의 상품 목록을 조회한다`() { - every { loadProductPort.loadAllProductByShopId(1L) } answers { + every { loadProductPort.loadAllProductByShopId(any()) } answers { listOf(Product(ProductId(1L), "부대찌개", Money.from(15000))) } val expected = listOf(ProductResponse(1L, "부대찌개", 15000)) - val actual = getProductService.loadAllProductByShopId(1L) + val actual = getProductService.loadAllProductByShopId(UUID.randomUUID()) actual shouldBe expected } diff --git a/mealkitary-application/src/test/kotlin/com/mealkitary/shop/application/service/GetReservableTimeServiceTest.kt b/mealkitary-application/src/test/kotlin/com/mealkitary/shop/application/service/GetReservableTimeServiceTest.kt index d443ef3..e15d02c 100644 --- a/mealkitary-application/src/test/kotlin/com/mealkitary/shop/application/service/GetReservableTimeServiceTest.kt +++ b/mealkitary-application/src/test/kotlin/com/mealkitary/shop/application/service/GetReservableTimeServiceTest.kt @@ -6,6 +6,7 @@ import io.kotest.matchers.shouldBe import io.mockk.every import io.mockk.mockk import java.time.LocalTime +import java.util.UUID class GetReservableTimeServiceTest : AnnotationSpec() { @@ -14,7 +15,7 @@ class GetReservableTimeServiceTest : AnnotationSpec() { @Test fun `service unit test - 가게 ID에 해당하는 가게의 모든 예약 가능 시간을 조회한다`() { - every { loadReservableTimePort.loadAllReservableTimeByShopId(1L) } answers { + every { loadReservableTimePort.loadAllReservableTimeByShopId(any()) } answers { listOf( LocalTime.of(6, 30), LocalTime.of(18, 30) @@ -25,7 +26,7 @@ class GetReservableTimeServiceTest : AnnotationSpec() { LocalTime.of(18, 30) ) - val actual = getReservableTimeService.loadAllReservableTimeByShopId(1L) + val actual = getReservableTimeService.loadAllReservableTimeByShopId(UUID.randomUUID()) actual shouldBe expected actual.size shouldBe 2 diff --git a/mealkitary-application/src/test/kotlin/com/mealkitary/shop/application/service/GetShopServiceTest.kt b/mealkitary-application/src/test/kotlin/com/mealkitary/shop/application/service/GetShopServiceTest.kt index 90f93eb..0b264d1 100644 --- a/mealkitary-application/src/test/kotlin/com/mealkitary/shop/application/service/GetShopServiceTest.kt +++ b/mealkitary-application/src/test/kotlin/com/mealkitary/shop/application/service/GetShopServiceTest.kt @@ -5,10 +5,10 @@ import com.mealkitary.common.model.Coordinates import com.mealkitary.shop.application.port.input.ShopResponse import com.mealkitary.shop.application.port.output.LoadShopPort import com.mealkitary.shop.domain.shop.Shop +import com.mealkitary.shop.domain.shop.ShopAddress import com.mealkitary.shop.domain.shop.ShopBusinessNumber import com.mealkitary.shop.domain.shop.ShopStatus import com.mealkitary.shop.domain.shop.ShopTitle -import com.mealkitary.shop.domain.shop.address.ShopAddress import io.kotest.core.spec.style.AnnotationSpec import io.kotest.matchers.shouldBe import io.mockk.every @@ -21,31 +21,33 @@ class GetShopServiceTest : AnnotationSpec() { @Test fun `service unit test - 모든 가게를 조회한다`() { + val shop = Shop( + ShopTitle.from("집밥뚝딱"), + ShopStatus.VALID, + ShopBusinessNumber.from("123-45-67890"), + ShopAddress.of( + "1234567890", + Coordinates.of( + 126.99599512792346, + 35.976749396987046 + ), + Address.of( + "region1DepthName", + "region2DepthName", + "region3DepthName", + "roadName" + ) + ), + mutableListOf(), + mutableListOf() + ) + every { loadShopPort.loadAllShop() } answers { listOf( - Shop( - ShopTitle.from("집밥뚝딱"), - ShopStatus.VALID, - ShopBusinessNumber.from("123-45-67890"), - ShopAddress.of( - "1234567890", - Coordinates.of( - 126.99599512792346, - 35.976749396987046 - ), - Address.of( - "region1DepthName", - "region2DepthName", - "region3DepthName", - "roadName" - ) - ), - mutableListOf(), - mutableListOf() - ) + shop ) } - val expected = ShopResponse(null, "집밥뚝딱") + val expected = ShopResponse(shop.id, "집밥뚝딱") val actual = getShopService.loadAllShop() diff --git a/mealkitary-application/src/test/kotlin/com/mealkitary/shop/application/service/RegisterShopServiceTest.kt b/mealkitary-application/src/test/kotlin/com/mealkitary/shop/application/service/RegisterShopServiceTest.kt index b3b57b5..97dab4a 100644 --- a/mealkitary-application/src/test/kotlin/com/mealkitary/shop/application/service/RegisterShopServiceTest.kt +++ b/mealkitary-application/src/test/kotlin/com/mealkitary/shop/application/service/RegisterShopServiceTest.kt @@ -6,10 +6,10 @@ import com.mealkitary.shop.application.port.input.RegisterShopRequest import com.mealkitary.shop.application.port.output.SaveShopPort import com.mealkitary.shop.domain.product.Product import com.mealkitary.shop.domain.shop.Shop +import com.mealkitary.shop.domain.shop.ShopAddress import com.mealkitary.shop.domain.shop.ShopBusinessNumber import com.mealkitary.shop.domain.shop.ShopStatus import com.mealkitary.shop.domain.shop.ShopTitle -import com.mealkitary.shop.domain.shop.address.ShopAddress import com.mealkitary.shop.domain.shop.factory.AddressResolver import com.mealkitary.shop.domain.shop.factory.ShopBusinessNumberValidator import com.mealkitary.shop.domain.shop.factory.ShopFactory @@ -22,6 +22,7 @@ import io.mockk.every import io.mockk.mockk import io.mockk.slot import java.time.LocalTime +import java.util.UUID class RegisterShopServiceTest : AnnotationSpec() { @@ -50,12 +51,13 @@ class RegisterShopServiceTest : AnnotationSpec() { every { shopFactory.createOne(request.title, request.brn, request.address) } returns mockedShop - every { saveShopPort.saveOne(capture(shopSlot)) } answers { 1L } + val expectedId = UUID.randomUUID() + every { saveShopPort.saveOne(capture(shopSlot)) } answers { expectedId } val result = registerShopService.register(request) val capturedShop = shopSlot.captured - result shouldBe 1L + result shouldBe expectedId capturedShop.businessNumber.value shouldBe "123-23-12345" capturedShop.title.value shouldBe "집밥뚝딱 안양점" capturedShop.address shouldBe expectedShopAddress @@ -72,7 +74,7 @@ class RegisterShopServiceTest : AnnotationSpec() { every { shopFactory.createOne(any(), any(), any()) } throws IllegalArgumentException("올바른 가게 이름 형식이 아닙니다.(한글, 영문, 공백, 숫자만 포함 가능)") - every { saveShopPort.saveOne(any()) } answers { 1L } + every { saveShopPort.saveOne(any()) } answers { UUID.randomUUID() } every { shopBusinessNumberValidator.validate(any()) } answers {} every { addressResolver.resolve("경기도 안양시 동안구 벌말로 40") } returns expectedShopAddress @@ -88,7 +90,7 @@ class RegisterShopServiceTest : AnnotationSpec() { every { shopFactory.createOne(any(), any(), any()) } throws IllegalArgumentException("올바른 사업자번호 형식이 아닙니다.") - every { saveShopPort.saveOne(any()) } answers { 1L } + every { saveShopPort.saveOne(any()) } answers { UUID.randomUUID() } every { shopBusinessNumberValidator.validate(any()) } answers {} shouldThrow { diff --git a/mealkitary-application/src/test/kotlin/com/mealkitary/shop/application/service/UpdateShopStatusServiceTest.kt b/mealkitary-application/src/test/kotlin/com/mealkitary/shop/application/service/UpdateShopStatusServiceTest.kt index d8e47f7..9d7a350 100644 --- a/mealkitary-application/src/test/kotlin/com/mealkitary/shop/application/service/UpdateShopStatusServiceTest.kt +++ b/mealkitary-application/src/test/kotlin/com/mealkitary/shop/application/service/UpdateShopStatusServiceTest.kt @@ -5,10 +5,10 @@ import com.mealkitary.common.model.Coordinates import com.mealkitary.shop.application.port.output.CheckExistenceShopPort import com.mealkitary.shop.application.port.output.LoadShopPort import com.mealkitary.shop.domain.shop.Shop +import com.mealkitary.shop.domain.shop.ShopAddress import com.mealkitary.shop.domain.shop.ShopBusinessNumber import com.mealkitary.shop.domain.shop.ShopStatus import com.mealkitary.shop.domain.shop.ShopTitle -import com.mealkitary.shop.domain.shop.address.ShopAddress import io.kotest.assertions.throwables.shouldThrow import io.kotest.core.spec.style.AnnotationSpec import io.kotest.matchers.shouldBe @@ -23,7 +23,6 @@ class UpdateShopStatusServiceTest : AnnotationSpec() { @Test fun `service unit test - 가게의 상태를 INVALID로 변경한다`() { - val shopId = 1L val validShop = Shop( ShopTitle.from("제목"), ShopStatus.VALID, @@ -45,17 +44,16 @@ class UpdateShopStatusServiceTest : AnnotationSpec() { mutableListOf() ) - every { loadShopPort.loadOneShopById(shopId) } returns validShop - every { checkExistenceShopPort.hasReservations(shopId) } returns false + every { loadShopPort.loadOneShopById(validShop.id) } returns validShop + every { checkExistenceShopPort.hasReservations(validShop.id) } returns false - updateShopStatusService.update(shopId) + updateShopStatusService.update(validShop.id) validShop.status shouldBe ShopStatus.INVALID } @Test fun `service unit test - 가게의 상태를 VALID로 변경한다`() { - val shopId = 1L val validShop = Shop( ShopTitle.from("제목"), ShopStatus.INVALID, @@ -77,10 +75,10 @@ class UpdateShopStatusServiceTest : AnnotationSpec() { mutableListOf() ) - every { loadShopPort.loadOneShopById(shopId) } returns validShop - every { checkExistenceShopPort.hasReservations(shopId) } returns false + every { loadShopPort.loadOneShopById(validShop.id) } returns validShop + every { checkExistenceShopPort.hasReservations(validShop.id) } returns false - updateShopStatusService.update(shopId) + updateShopStatusService.update(validShop.id) validShop.status shouldBe ShopStatus.VALID } @@ -109,11 +107,11 @@ class UpdateShopStatusServiceTest : AnnotationSpec() { mutableListOf() ) - every { loadShopPort.loadOneShopById(shopId) } returns validShop - every { checkExistenceShopPort.hasReservations(shopId) } returns true + every { loadShopPort.loadOneShopById(validShop.id) } returns validShop + every { checkExistenceShopPort.hasReservations(validShop.id) } returns true shouldThrow { - updateShopStatusService.update(shopId) + updateShopStatusService.update(validShop.id) } } } diff --git a/mealkitary-domain/src/main/kotlin/com/mealkitary/shop/domain/shop/Shop.kt b/mealkitary-domain/src/main/kotlin/com/mealkitary/shop/domain/shop/Shop.kt index 352c3cc..f7e80a2 100644 --- a/mealkitary-domain/src/main/kotlin/com/mealkitary/shop/domain/shop/Shop.kt +++ b/mealkitary-domain/src/main/kotlin/com/mealkitary/shop/domain/shop/Shop.kt @@ -1,7 +1,7 @@ package com.mealkitary.shop.domain.shop +import com.mealkitary.common.model.UUIDBaseEntity import com.mealkitary.shop.domain.product.Product -import com.mealkitary.shop.domain.shop.address.ShopAddress import java.time.LocalDateTime import java.time.LocalTime import javax.persistence.CascadeType @@ -11,9 +11,6 @@ import javax.persistence.ElementCollection import javax.persistence.Entity import javax.persistence.EnumType import javax.persistence.Enumerated -import javax.persistence.GeneratedValue -import javax.persistence.GenerationType -import javax.persistence.Id import javax.persistence.JoinColumn import javax.persistence.OneToMany import javax.persistence.Table @@ -27,13 +24,7 @@ class Shop( address: ShopAddress, reservableTimes: MutableList, products: MutableList -) { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "shop_id") - var id: Long? = null - protected set +) : UUIDBaseEntity() { @Column(nullable = false) var title: ShopTitle = title diff --git a/mealkitary-domain/src/main/kotlin/com/mealkitary/shop/domain/shop/address/ShopAddress.kt b/mealkitary-domain/src/main/kotlin/com/mealkitary/shop/domain/shop/ShopAddress.kt similarity index 95% rename from mealkitary-domain/src/main/kotlin/com/mealkitary/shop/domain/shop/address/ShopAddress.kt rename to mealkitary-domain/src/main/kotlin/com/mealkitary/shop/domain/shop/ShopAddress.kt index 2229f42..18a1dca 100644 --- a/mealkitary-domain/src/main/kotlin/com/mealkitary/shop/domain/shop/address/ShopAddress.kt +++ b/mealkitary-domain/src/main/kotlin/com/mealkitary/shop/domain/shop/ShopAddress.kt @@ -1,4 +1,4 @@ -package com.mealkitary.shop.domain.shop.address +package com.mealkitary.shop.domain.shop import com.mealkitary.common.model.Address import com.mealkitary.common.model.Coordinates diff --git a/mealkitary-domain/src/main/kotlin/com/mealkitary/shop/domain/shop/factory/AddressResolver.kt b/mealkitary-domain/src/main/kotlin/com/mealkitary/shop/domain/shop/factory/AddressResolver.kt index 70cb6e8..a79b7fc 100644 --- a/mealkitary-domain/src/main/kotlin/com/mealkitary/shop/domain/shop/factory/AddressResolver.kt +++ b/mealkitary-domain/src/main/kotlin/com/mealkitary/shop/domain/shop/factory/AddressResolver.kt @@ -1,6 +1,6 @@ package com.mealkitary.shop.domain.shop.factory -import com.mealkitary.shop.domain.shop.address.ShopAddress +import com.mealkitary.shop.domain.shop.ShopAddress interface AddressResolver { diff --git a/mealkitary-domain/src/main/kotlin/com/mealkitary/shop/domain/shop/factory/ShopFactory.kt b/mealkitary-domain/src/main/kotlin/com/mealkitary/shop/domain/shop/factory/ShopFactory.kt index a1d52ab..262d6bb 100644 --- a/mealkitary-domain/src/main/kotlin/com/mealkitary/shop/domain/shop/factory/ShopFactory.kt +++ b/mealkitary-domain/src/main/kotlin/com/mealkitary/shop/domain/shop/factory/ShopFactory.kt @@ -2,10 +2,10 @@ package com.mealkitary.shop.domain.shop.factory import com.mealkitary.shop.domain.product.Product import com.mealkitary.shop.domain.shop.Shop +import com.mealkitary.shop.domain.shop.ShopAddress import com.mealkitary.shop.domain.shop.ShopBusinessNumber import com.mealkitary.shop.domain.shop.ShopStatus import com.mealkitary.shop.domain.shop.ShopTitle -import com.mealkitary.shop.domain.shop.address.ShopAddress import org.springframework.stereotype.Component import java.time.LocalTime diff --git a/mealkitary-domain/src/test/kotlin/com/mealkitary/shop/domain/shop/ShopAddressTest.kt b/mealkitary-domain/src/test/kotlin/com/mealkitary/shop/domain/shop/ShopAddressTest.kt index d490ebd..8024514 100644 --- a/mealkitary-domain/src/test/kotlin/com/mealkitary/shop/domain/shop/ShopAddressTest.kt +++ b/mealkitary-domain/src/test/kotlin/com/mealkitary/shop/domain/shop/ShopAddressTest.kt @@ -2,7 +2,6 @@ package com.mealkitary.shop.domain.shop import com.mealkitary.common.model.Address import com.mealkitary.common.model.Coordinates -import com.mealkitary.shop.domain.shop.address.ShopAddress import io.kotest.assertions.throwables.shouldThrow import io.kotest.core.spec.style.AnnotationSpec import io.kotest.matchers.shouldBe diff --git a/mealkitary-domain/src/test/kotlin/com/mealkitary/shop/domain/shop/factory/ShopFactoryTest.kt b/mealkitary-domain/src/test/kotlin/com/mealkitary/shop/domain/shop/factory/ShopFactoryTest.kt index 899d5fa..a63526c 100644 --- a/mealkitary-domain/src/test/kotlin/com/mealkitary/shop/domain/shop/factory/ShopFactoryTest.kt +++ b/mealkitary-domain/src/test/kotlin/com/mealkitary/shop/domain/shop/factory/ShopFactoryTest.kt @@ -2,7 +2,7 @@ package com.mealkitary.shop.domain.shop.factory import com.mealkitary.common.model.Address import com.mealkitary.common.model.Coordinates -import com.mealkitary.shop.domain.shop.address.ShopAddress +import com.mealkitary.shop.domain.shop.ShopAddress import io.kotest.assertions.throwables.shouldThrow import io.kotest.core.spec.style.AnnotationSpec import io.kotest.matchers.shouldBe diff --git a/mealkitary-domain/src/testFixtures/kotlin/data/ShopTestData.kt b/mealkitary-domain/src/testFixtures/kotlin/data/ShopTestData.kt index 968438f..6f0cfb2 100644 --- a/mealkitary-domain/src/testFixtures/kotlin/data/ShopTestData.kt +++ b/mealkitary-domain/src/testFixtures/kotlin/data/ShopTestData.kt @@ -4,10 +4,10 @@ import com.mealkitary.common.model.Address import com.mealkitary.common.model.Coordinates import com.mealkitary.shop.domain.product.Product import com.mealkitary.shop.domain.shop.Shop +import com.mealkitary.shop.domain.shop.ShopAddress import com.mealkitary.shop.domain.shop.ShopBusinessNumber import com.mealkitary.shop.domain.shop.ShopStatus import com.mealkitary.shop.domain.shop.ShopTitle -import com.mealkitary.shop.domain.shop.address.ShopAddress import data.ProductTestData.Companion.defaultProduct import java.time.LocalTime diff --git a/mealkitary-infrastructure/adapter-address-resolver/kakao-api-address-resolver/src/main/kotlin/com/mealkitary/address/KakaoApiAddressResolver.kt b/mealkitary-infrastructure/adapter-address-resolver/kakao-api-address-resolver/src/main/kotlin/com/mealkitary/address/KakaoApiAddressResolver.kt index 6a5e1b1..e510e01 100644 --- a/mealkitary-infrastructure/adapter-address-resolver/kakao-api-address-resolver/src/main/kotlin/com/mealkitary/address/KakaoApiAddressResolver.kt +++ b/mealkitary-infrastructure/adapter-address-resolver/kakao-api-address-resolver/src/main/kotlin/com/mealkitary/address/KakaoApiAddressResolver.kt @@ -2,7 +2,7 @@ package com.mealkitary.address import com.mealkitary.common.model.Address import com.mealkitary.common.model.Coordinates -import com.mealkitary.shop.domain.shop.address.ShopAddress +import com.mealkitary.shop.domain.shop.ShopAddress import com.mealkitary.shop.domain.shop.factory.AddressResolver import org.springframework.context.annotation.Primary import org.springframework.stereotype.Component diff --git a/mealkitary-infrastructure/adapter-address-resolver/simple-address-resolver/src/main/java/com/mealkitary/SimpleAddressResolver.kt b/mealkitary-infrastructure/adapter-address-resolver/simple-address-resolver/src/main/java/com/mealkitary/SimpleAddressResolver.kt index 90b20dd..4bd5799 100644 --- a/mealkitary-infrastructure/adapter-address-resolver/simple-address-resolver/src/main/java/com/mealkitary/SimpleAddressResolver.kt +++ b/mealkitary-infrastructure/adapter-address-resolver/simple-address-resolver/src/main/java/com/mealkitary/SimpleAddressResolver.kt @@ -2,7 +2,7 @@ package com.mealkitary import com.mealkitary.common.model.Address import com.mealkitary.common.model.Coordinates -import com.mealkitary.shop.domain.shop.address.ShopAddress +import com.mealkitary.shop.domain.shop.ShopAddress import com.mealkitary.shop.domain.shop.factory.AddressResolver import org.springframework.stereotype.Component diff --git a/mealkitary-infrastructure/adapter-persistence-spring-data-jpa/src/main/kotlin/com/mealkitary/reservation/persistence/ReservationRepository.kt b/mealkitary-infrastructure/adapter-persistence-spring-data-jpa/src/main/kotlin/com/mealkitary/reservation/persistence/ReservationRepository.kt index 470c588..f4aad43 100644 --- a/mealkitary-infrastructure/adapter-persistence-spring-data-jpa/src/main/kotlin/com/mealkitary/reservation/persistence/ReservationRepository.kt +++ b/mealkitary-infrastructure/adapter-persistence-spring-data-jpa/src/main/kotlin/com/mealkitary/reservation/persistence/ReservationRepository.kt @@ -11,7 +11,7 @@ interface ReservationRepository : JpaRepository { @EntityGraph(attributePaths = ["shop"]) fun findOneWithShopById(reservationId: UUID): Optional - fun findAllByShopId(shopId: Long): List + fun findAllByShopId(shopId: UUID): List - fun existsReservationByShopId(shopId: Long): Boolean + fun existsReservationByShopId(shopId: UUID): Boolean } diff --git a/mealkitary-infrastructure/adapter-persistence-spring-data-jpa/src/main/kotlin/com/mealkitary/reservation/persistence/SpringDataJpaReservationPersistenceAdapter.kt b/mealkitary-infrastructure/adapter-persistence-spring-data-jpa/src/main/kotlin/com/mealkitary/reservation/persistence/SpringDataJpaReservationPersistenceAdapter.kt index c3a1a27..bd934bd 100644 --- a/mealkitary-infrastructure/adapter-persistence-spring-data-jpa/src/main/kotlin/com/mealkitary/reservation/persistence/SpringDataJpaReservationPersistenceAdapter.kt +++ b/mealkitary-infrastructure/adapter-persistence-spring-data-jpa/src/main/kotlin/com/mealkitary/reservation/persistence/SpringDataJpaReservationPersistenceAdapter.kt @@ -50,7 +50,7 @@ class SpringDataJpaReservationPersistenceAdapter( return mapToReservationResponse(reservation) } - override fun queryAllReservationByShopId(shopId: Long): List { + override fun queryAllReservationByShopId(shopId: UUID): List { val reservations = reservationRepository.findAllByShopId(shopId) return reservations.map { mapToReservationResponse(it) } diff --git a/mealkitary-infrastructure/adapter-persistence-spring-data-jpa/src/main/kotlin/com/mealkitary/shop/persistence/ShopRepository.kt b/mealkitary-infrastructure/adapter-persistence-spring-data-jpa/src/main/kotlin/com/mealkitary/shop/persistence/ShopRepository.kt index 5bc76e4..c6f33f0 100644 --- a/mealkitary-infrastructure/adapter-persistence-spring-data-jpa/src/main/kotlin/com/mealkitary/shop/persistence/ShopRepository.kt +++ b/mealkitary-infrastructure/adapter-persistence-spring-data-jpa/src/main/kotlin/com/mealkitary/shop/persistence/ShopRepository.kt @@ -4,12 +4,13 @@ import com.mealkitary.shop.domain.shop.Shop import org.springframework.data.jpa.repository.EntityGraph import org.springframework.data.jpa.repository.JpaRepository import java.util.Optional +import java.util.UUID interface ShopRepository : JpaRepository { @EntityGraph(attributePaths = ["products"]) - fun findOneWithProductsById(shopId: Long): Optional + fun findOneWithProductsById(shopId: UUID): Optional @EntityGraph(attributePaths = ["reservableTimes"]) - fun findOneWithReservableTimesById(shopId: Long): Optional + fun findOneWithReservableTimesById(shopId: UUID): Optional } diff --git a/mealkitary-infrastructure/adapter-persistence-spring-data-jpa/src/main/kotlin/com/mealkitary/shop/persistence/SpringDataJpaShopPersistenceAdapter.kt b/mealkitary-infrastructure/adapter-persistence-spring-data-jpa/src/main/kotlin/com/mealkitary/shop/persistence/SpringDataJpaShopPersistenceAdapter.kt index 2478922..ceaa419 100644 --- a/mealkitary-infrastructure/adapter-persistence-spring-data-jpa/src/main/kotlin/com/mealkitary/shop/persistence/SpringDataJpaShopPersistenceAdapter.kt +++ b/mealkitary-infrastructure/adapter-persistence-spring-data-jpa/src/main/kotlin/com/mealkitary/shop/persistence/SpringDataJpaShopPersistenceAdapter.kt @@ -10,6 +10,7 @@ import com.mealkitary.shop.application.port.output.SaveShopPort import com.mealkitary.shop.domain.shop.Shop import org.springframework.stereotype.Repository import java.util.Optional +import java.util.UUID import java.util.function.Function private const val NOT_FOUND_SHOP_MESSAGE = "존재하지 않는 가게입니다." @@ -20,27 +21,27 @@ class SpringDataJpaShopPersistenceAdapter( private val reservationRepository: ReservationRepository ) : SaveShopPort, LoadShopPort, LoadProductPort, LoadReservableTimePort, CheckExistenceShopPort { - override fun saveOne(shop: Shop): Long { + override fun saveOne(shop: Shop): UUID { shopRepository.save(shop) - return shop.id!! + return shop.id } override fun loadAllShop(): List = shopRepository.findAll() - override fun loadOneShopById(shopId: Long) = getShopOrThrow(shopRepository::findOneWithProductsById, shopId) + override fun loadOneShopById(shopId: UUID) = getShopOrThrow(shopRepository::findOneWithProductsById, shopId) - override fun loadAllProductByShopId(shopId: Long) = + override fun loadAllProductByShopId(shopId: UUID) = getShopOrThrow(shopRepository::findOneWithProductsById, shopId).products - override fun loadAllReservableTimeByShopId(shopId: Long) = + override fun loadAllReservableTimeByShopId(shopId: UUID) = getShopOrThrow(shopRepository::findOneWithReservableTimesById, shopId).reservableTimes - override fun hasReservations(shopId: Long): Boolean { + override fun hasReservations(shopId: UUID): Boolean { return reservationRepository.existsReservationByShopId(shopId) } - private fun getShopOrThrow(queryMethod: Function>, shopId: Long): Shop { + private fun getShopOrThrow(queryMethod: Function>, shopId: UUID): Shop { return (queryMethod.apply(shopId).orElseThrow { throw EntityNotFoundException(NOT_FOUND_SHOP_MESSAGE) }) } } diff --git a/mealkitary-infrastructure/adapter-persistence-spring-data-jpa/src/main/resources/data.sql b/mealkitary-infrastructure/adapter-persistence-spring-data-jpa/src/main/resources/data.sql index ab9372a..107d5e7 100644 --- a/mealkitary-infrastructure/adapter-persistence-spring-data-jpa/src/main/resources/data.sql +++ b/mealkitary-infrastructure/adapter-persistence-spring-data-jpa/src/main/resources/data.sql @@ -1,57 +1,62 @@ insert into shop -values (1, '경기도', '광명시', '철산동', '철산로', '1234567890', 30.03, 50.05, '123-12-12345', 'VALID', '집밥뚝딱 철산점'); +values ('e9e3fcaf-e665-4b95-8e52-958c8f6c8163', '경기도', '광명시', '철산동', '철산로', '1234567890', 30.03, 50.05, '123-12-12345', + 'VALID', '집밥뚝딱 철산점'); insert into product -values (1, '부대찌개', 15800, 1); +values (1, '부대찌개', 15800, 'e9e3fcaf-e665-4b95-8e52-958c8f6c8163'); insert into product -values (2, '존슨탕', 19600, 1); +values (2, '존슨탕', 19600, 'e9e3fcaf-e665-4b95-8e52-958c8f6c8163'); insert into product -values (3, '소불고기 샤브샤브', 13200, 1); +values (3, '소불고기 샤브샤브', 13200, 'e9e3fcaf-e665-4b95-8e52-958c8f6c8163'); insert into reservable_time -values (1, '06:30'); +values ('e9e3fcaf-e665-4b95-8e52-958c8f6c8163', '06:30'); insert into reservable_time -values (1, '09:30'); +values ('e9e3fcaf-e665-4b95-8e52-958c8f6c8163', '09:30'); insert into reservable_time -values (1, '12:30'); +values ('e9e3fcaf-e665-4b95-8e52-958c8f6c8163', '12:30'); insert into reservable_time -values (1, '18:30'); +values ('e9e3fcaf-e665-4b95-8e52-958c8f6c8163', '18:30'); insert into shop -values (2, '경기도', '안양시', '동안구', '경수대로', '1234567890', 30.03, 50.05, '123-12-12345', 'VALID', '집밥뚝딱 안양점'); +values ('f8445ab4-2ede-4db2-b9de-9fb21cffa2d2', '경기도', '안양시', '동안구', '경수대로', '1234567890', 30.03, 50.05, '123-12-12345', + 'VALID', '집밥뚝딱 안양점'); insert into product -values (4, '비비고 만두', 3200, 2); +values (4, '비비고 만두', 3200, 'f8445ab4-2ede-4db2-b9de-9fb21cffa2d2'); insert into product -values (5, '토마토 훠궈', 22000, 2); +values (5, '토마토 훠궈', 22000, 'f8445ab4-2ede-4db2-b9de-9fb21cffa2d2'); insert into product -values (6, '닭가슴살 샐러드', 6600, 2); +values (6, '닭가슴살 샐러드', 6600, 'f8445ab4-2ede-4db2-b9de-9fb21cffa2d2'); insert into reservable_time -values (2, '12:30'); +values ('f8445ab4-2ede-4db2-b9de-9fb21cffa2d2', '12:30'); insert into reservable_time -values (2, '19:30'); +values ('f8445ab4-2ede-4db2-b9de-9fb21cffa2d2', '19:30'); insert into shop -values (3, '서울시', '동작구', '상도동', '', '1234567890', 30.03, 50.05, '123-12-12345', 'VALID', '집밥뚝딱 숭실대입구점'); +values ('b1f1c9a0-20ac-43e9-9126-384a7fb19ff9', '서울시', '동작구', '상도동', '', '1234567890', 30.03, 50.05, '123-12-12345', + 'VALID', '집밥뚝딱 숭실대입구점'); insert into product -values (7, '왕만두', 4900, 3); +values (7, '왕만두', 4900, 'b1f1c9a0-20ac-43e9-9126-384a7fb19ff9'); insert into product -values (8, '토마토 파스타', 8800, 3); +values (8, '토마토 파스타', 8800, 'b1f1c9a0-20ac-43e9-9126-384a7fb19ff9'); insert into product -values (9, '알리오올리오 파스타', 9900, 3); +values (9, '알리오올리오 파스타', 9900, 'b1f1c9a0-20ac-43e9-9126-384a7fb19ff9'); insert into reservable_time -values (3, '16:30'); +values ('b1f1c9a0-20ac-43e9-9126-384a7fb19ff9', '16:30'); insert into reservable_time -values (3, '18:30'); +values ('b1f1c9a0-20ac-43e9-9126-384a7fb19ff9', '18:30'); insert into reservable_time -values (3, '20:00'); +values ('b1f1c9a0-20ac-43e9-9126-384a7fb19ff9', '20:00'); insert into reservable_time -values (3, '23:30'); +values ('b1f1c9a0-20ac-43e9-9126-384a7fb19ff9', '23:30'); insert into shop -values (4, '경기도', '남양주시', '다산동', '', '1234567890', 30.03, 50.05, '123-12-12345', 'VALID', '집밥뚝딱 다산점'); +values ('e390fc56-1e06-435a-93a4-1157db489a9d', '경기도', '남양주시', '다산동', '', '1234567890', 30.03, 50.05, '123-12-12345', + 'VALID', '집밥뚝딱 다산점'); insert into product -values (10, '김치찌개', 15800, 4); +values (10, '김치찌개', 15800, 'e390fc56-1e06-435a-93a4-1157db489a9d'); insert into reservable_time -values (4, '16:30'); +values ('e390fc56-1e06-435a-93a4-1157db489a9d', '16:30'); insert into reservation (id, shop_id, reserve_at, reservation_status) -values ('c1e170e4-57e4-4d7d-8c10-6f4a8c658020', 4, '2023-09-22T16:30:00', 'NOTPAID'); +values ('c1e170e4-57e4-4d7d-8c10-6f4a8c658020', 'e390fc56-1e06-435a-93a4-1157db489a9d', '2023-09-22T16:30:00', + 'NOTPAID'); diff --git a/mealkitary-infrastructure/adapter-persistence-spring-data-jpa/src/test/kotlin/com/mealkitary/reservation/persistence/SpringDataJpaReservationPersistenceAdapterTest.kt b/mealkitary-infrastructure/adapter-persistence-spring-data-jpa/src/test/kotlin/com/mealkitary/reservation/persistence/SpringDataJpaReservationPersistenceAdapterTest.kt index f674e75..07eb48f 100644 --- a/mealkitary-infrastructure/adapter-persistence-spring-data-jpa/src/test/kotlin/com/mealkitary/reservation/persistence/SpringDataJpaReservationPersistenceAdapterTest.kt +++ b/mealkitary-infrastructure/adapter-persistence-spring-data-jpa/src/test/kotlin/com/mealkitary/reservation/persistence/SpringDataJpaReservationPersistenceAdapterTest.kt @@ -23,7 +23,10 @@ class SpringDataJpaReservationPersistenceAdapterTest( @Test fun `db integration test - 신규 예약을 저장한다`() { val reservation = ReservationTestData.defaultReservation() - .withShop(shopRepository.findOneWithProductsById(1L).orElseThrow()) + .withShop( + shopRepository.findOneWithProductsById(UUID.fromString("e9e3fcaf-e665-4b95-8e52-958c8f6c8163")) + .orElseThrow() + ) .build() val saved = adapterUnderTest.saveOne(reservation) @@ -38,7 +41,10 @@ class SpringDataJpaReservationPersistenceAdapterTest( fun `db integration test - 신규 결제를 저장한다`() { val reservation = ReservationTestData.defaultReservation() .withReservationStatus(ReservationStatus.NOTPAID) - .withShop(shopRepository.findOneWithProductsById(1L).orElseThrow()) + .withShop( + shopRepository.findOneWithProductsById(UUID.fromString("e9e3fcaf-e665-4b95-8e52-958c8f6c8163")) + .orElseThrow() + ) .build() val payment = Payment.of( "paymentKey", @@ -61,7 +67,10 @@ class SpringDataJpaReservationPersistenceAdapterTest( fun `db integration test - 예약을 조회한다`() { val reservation = ReservationTestData.defaultReservation() .withReservationStatus(ReservationStatus.NOTPAID) - .withShop(shopRepository.findOneWithProductsById(1L).orElseThrow()) + .withShop( + shopRepository.findOneWithProductsById(UUID.fromString("e9e3fcaf-e665-4b95-8e52-958c8f6c8163")) + .orElseThrow() + ) .build() val saved = adapterUnderTest.saveOne(reservation) em.flush() @@ -77,7 +86,10 @@ class SpringDataJpaReservationPersistenceAdapterTest( fun `db integration test - 예약의 상세 정보를 조회한다`() { val reservation = ReservationTestData.defaultReservation() .withReservationStatus(ReservationStatus.NOTPAID) - .withShop(shopRepository.findOneWithProductsById(1L).orElseThrow()) + .withShop( + shopRepository.findOneWithProductsById(UUID.fromString("e9e3fcaf-e665-4b95-8e52-958c8f6c8163")) + .orElseThrow() + ) .build() val saved = adapterUnderTest.saveOne(reservation) em.flush() @@ -96,13 +108,17 @@ class SpringDataJpaReservationPersistenceAdapterTest( fun `db integration test - 가게 식별자로 예약의 상세 정보 목록을 조회한다`() { val reservation = ReservationTestData.defaultReservation() .withReservationStatus(ReservationStatus.NOTPAID) - .withShop(shopRepository.findOneWithProductsById(1L).orElseThrow()) + .withShop( + shopRepository.findOneWithProductsById(UUID.fromString("e9e3fcaf-e665-4b95-8e52-958c8f6c8163")) + .orElseThrow() + ) .build() val saved = adapterUnderTest.saveOne(reservation) em.flush() em.clear() - val result = adapterUnderTest.queryAllReservationByShopId(1L) + val result = + adapterUnderTest.queryAllReservationByShopId(UUID.fromString("e9e3fcaf-e665-4b95-8e52-958c8f6c8163")) val resultReservation = result.get(0) result.size shouldBe 1 @@ -115,8 +131,8 @@ class SpringDataJpaReservationPersistenceAdapterTest( @Test fun `db integration test - 가게 식별자로 예약의 상세 목록을 조회할 때, 관련 데이터가 없으면 빈 리스트를 반환한다`() { - val unknownShopId = 12345L - val noReservationShopId = 1L + val unknownShopId = UUID.randomUUID() + val noReservationShopId = UUID.fromString("e9e3fcaf-e665-4b95-8e52-958c8f6c8163") val source = listOf(unknownShopId, noReservationShopId) source.forAll { @@ -130,7 +146,10 @@ class SpringDataJpaReservationPersistenceAdapterTest( fun `db integration test - 결제를 조회한다`() { val reservation = ReservationTestData.defaultReservation() .withReservationStatus(ReservationStatus.NOTPAID) - .withShop(shopRepository.findOneWithProductsById(1L).orElseThrow()) + .withShop( + shopRepository.findOneWithProductsById(UUID.fromString("e9e3fcaf-e665-4b95-8e52-958c8f6c8163")) + .orElseThrow() + ) .build() val payment = Payment.of( "paymentKey", diff --git a/mealkitary-infrastructure/adapter-persistence-spring-data-jpa/src/test/kotlin/com/mealkitary/shop/persistence/SpringDataJpaShopPersistenceAdapterTest.kt b/mealkitary-infrastructure/adapter-persistence-spring-data-jpa/src/test/kotlin/com/mealkitary/shop/persistence/SpringDataJpaShopPersistenceAdapterTest.kt index 5e7ced3..d763a2c 100644 --- a/mealkitary-infrastructure/adapter-persistence-spring-data-jpa/src/test/kotlin/com/mealkitary/shop/persistence/SpringDataJpaShopPersistenceAdapterTest.kt +++ b/mealkitary-infrastructure/adapter-persistence-spring-data-jpa/src/test/kotlin/com/mealkitary/shop/persistence/SpringDataJpaShopPersistenceAdapterTest.kt @@ -11,6 +11,7 @@ import io.kotest.matchers.collections.shouldBeEmpty import io.kotest.matchers.shouldBe import io.kotest.matchers.throwable.shouldHaveMessage import java.time.LocalTime +import java.util.UUID class SpringDataJpaShopPersistenceAdapterTest( private val adapterUnderTest: SpringDataJpaShopPersistenceAdapter, @@ -38,7 +39,8 @@ class SpringDataJpaShopPersistenceAdapterTest( } fun `db integration test - 가게에 예약이 존재하는지 확인한다`() { - val existsReservation = adapterUnderTest.hasReservations(4L) + val existsReservation = + adapterUnderTest.hasReservations(UUID.fromString("e390fc56-1e06-435a-93a4-1157db489a9d")) existsReservation.shouldBeTrue() } @@ -53,7 +55,7 @@ class SpringDataJpaShopPersistenceAdapterTest( @Test fun `db integration test - 가게 ID에 해당하는 가게의 상품 목록을 조회한다`() { - val products = adapterUnderTest.loadAllProductByShopId(1L) + val products = adapterUnderTest.loadAllProductByShopId(UUID.fromString("e9e3fcaf-e665-4b95-8e52-958c8f6c8163")) products.size shouldBe 3 products.get(0).name shouldBe "부대찌개" @@ -63,13 +65,13 @@ class SpringDataJpaShopPersistenceAdapterTest( @Test fun `db integration test - 가게 ID에 해당하는 가게의 상품 목록을 조회할 때, 해당 가게가 존재하지 않는 경우 예외를 발생한다`() { shouldThrow { - adapterUnderTest.loadAllProductByShopId(99L) + adapterUnderTest.loadAllProductByShopId(UUID.randomUUID()) } shouldHaveMessage "존재하지 않는 가게입니다." } @Test fun `db integration test - 가게 ID에 해당하는 가게를 조회하는데, 프로덕트도 함께 로드된다`() { - val shop = adapterUnderTest.loadOneShopById(1L) + val shop = adapterUnderTest.loadOneShopById(UUID.fromString("e9e3fcaf-e665-4b95-8e52-958c8f6c8163")) emf.persistenceUnitUtil.isLoaded(shop.products).shouldBeTrue() shop.title.value shouldBe "집밥뚝딱 철산점" @@ -80,13 +82,14 @@ class SpringDataJpaShopPersistenceAdapterTest( @Test fun `db integration test - 가게 ID에 해당하는 가게를 조회할 때, 해당 가게가 존재하지 않는 경우 예외를 발생한다`() { shouldThrow { - adapterUnderTest.loadOneShopById(99L) + adapterUnderTest.loadOneShopById(UUID.randomUUID()) } shouldHaveMessage "존재하지 않는 가게입니다." } @Test fun `db integration test - 가게 ID에 해당하는 가게의 모든 예약 가능 시간을 조회한다`() { - val reservableTimes = adapterUnderTest.loadAllReservableTimeByShopId(1L) + val reservableTimes = + adapterUnderTest.loadAllReservableTimeByShopId(UUID.fromString("e9e3fcaf-e665-4b95-8e52-958c8f6c8163")) reservableTimes.size shouldBe 4 reservableTimes.get(0) shouldBe LocalTime.of(6, 30) @@ -95,18 +98,19 @@ class SpringDataJpaShopPersistenceAdapterTest( @Test fun `db integration test - 가게 ID에 해당하는 가게의 모든 예약 가능 시간을 조회할 때, 해당 가게가 존재하지 않는 경우 예외를 발생한다`() { shouldThrow { - adapterUnderTest.loadAllReservableTimeByShopId(99L) + adapterUnderTest.loadAllReservableTimeByShopId(UUID.randomUUID()) } shouldHaveMessage "존재하지 않는 가게입니다." } @Test fun `db integration test - 가게 ID에 해당하는 가게의 예약 시간이 없는 경우 빈 배열을 반환한다`() { - val shop = adapterUnderTest.loadOneShopById(1L) + val shop = adapterUnderTest.loadOneShopById(UUID.fromString("e9e3fcaf-e665-4b95-8e52-958c8f6c8163")) shop.reservableTimes.clear() em.flush() em.clear() - val reservableTimes = adapterUnderTest.loadAllReservableTimeByShopId(1L) + val reservableTimes = + adapterUnderTest.loadAllReservableTimeByShopId(UUID.fromString("e9e3fcaf-e665-4b95-8e52-958c8f6c8163")) reservableTimes.shouldBeEmpty() } @@ -116,7 +120,7 @@ class SpringDataJpaShopPersistenceAdapterTest( em.createQuery("delete from Product p") .executeUpdate() - val products = adapterUnderTest.loadAllProductByShopId(1L) + val products = adapterUnderTest.loadAllProductByShopId(UUID.fromString("e9e3fcaf-e665-4b95-8e52-958c8f6c8163")) products.shouldBeEmpty() }