From 6cc9211dc8ea1479c022784e2a02db09cd4c1b3d Mon Sep 17 00:00:00 2001 From: June <68291395+june-777@users.noreply.github.com> Date: Mon, 19 Aug 2024 20:14:59 +0900 Subject: [PATCH] =?UTF-8?q?[feat]=20=EA=B5=AC=EB=A7=A4=EC=9E=90=20?= =?UTF-8?q?=EB=A7=A4=EC=9E=A5=EC=83=81=EC=84=B8=EC=A1=B0=ED=9A=8C=20(#106)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [feat] 구매자 매장 상세 조회 서비스 * [feat] 구매자 매장 상세 조회 Response 객체 - 구매자는 기본적인 매장 상세 정보를 확인할 수 있어야 함 * [feat] 가게주소, 가게카테고리에 대한 getter 추가 호출자 쪽에서의 getter depth 를 줄이기 위함 * [feat] 가게 id로 메뉴 목록을 조회하는 기능 * [feat] 가게 전시 응답에 가게 메뉴를 포함 * [feat] getter 추가 * [feat] 가게 전시 API 엔드포인트 구현 * [refactor] 가게 전시 메서드 이름 변경 * [test] 가게 전시 서비스 계층 단위 테스트 - responseDTO 을 적절히 매핑하여 반환하는지 테스트하기 위함 * [test] 가게 전시 API 컨트롤러 계층 단위 테스트 - API response 명세를 검증 및 추적하기 위함 * [text] 가게 조회 API 단위 테스트 - 메뉴 리스트 검증하도록 수정 및 테스트 * [merge] 머지 컨플릭트 해결 --- .../camp/woowak/lab/menu/domain/Menu.java | 9 + .../woowak/lab/menu/domain/MenuCategory.java | 5 +- .../lab/menu/repository/MenuRepository.java | 2 + .../lab/order/service/dto/OrderDTO.java | 2 +- .../camp/woowak/lab/store/domain/Store.java | 30 ++++ .../woowak/lab/store/domain/StoreAddress.java | 3 + .../store/service/StoreDisplayService.java | 46 +++++ .../response/StoreDisplayResponse.java | 70 ++++++++ .../lab/web/api/store/StoreApiController.java | 8 + .../service/StoreDisplayServiceTest.java | 158 ++++++++++++++++++ .../web/api/store/StoreApiControllerTest.java | 83 +++++++++ 11 files changed, 412 insertions(+), 4 deletions(-) create mode 100644 src/main/java/camp/woowak/lab/store/service/StoreDisplayService.java create mode 100644 src/main/java/camp/woowak/lab/store/service/response/StoreDisplayResponse.java create mode 100644 src/test/java/camp/woowak/lab/store/service/StoreDisplayServiceTest.java diff --git a/src/main/java/camp/woowak/lab/menu/domain/Menu.java b/src/main/java/camp/woowak/lab/menu/domain/Menu.java index fa0d10b4..66b8d890 100644 --- a/src/main/java/camp/woowak/lab/menu/domain/Menu.java +++ b/src/main/java/camp/woowak/lab/menu/domain/Menu.java @@ -78,4 +78,13 @@ public long updatePrice(long uPrice) { return this.price; } + + public Long getMenuCategoryId() { + return menuCategory.getId(); + } + + public String getMenuCategoryName() { + return menuCategory.getName(); + } + } diff --git a/src/main/java/camp/woowak/lab/menu/domain/MenuCategory.java b/src/main/java/camp/woowak/lab/menu/domain/MenuCategory.java index 3f9b3e77..21c808f5 100644 --- a/src/main/java/camp/woowak/lab/menu/domain/MenuCategory.java +++ b/src/main/java/camp/woowak/lab/menu/domain/MenuCategory.java @@ -12,6 +12,7 @@ import jakarta.persistence.Table; import jakarta.persistence.UniqueConstraint; import lombok.AccessLevel; +import lombok.Getter; import lombok.NoArgsConstructor; @Entity @@ -22,6 +23,7 @@ @UniqueConstraint(name = "unique_store_name", columnNames = {"store_id", "name"}) } ) +@Getter public class MenuCategory { @Id @@ -41,8 +43,5 @@ public MenuCategory(Store store, String name) { this.name = name; } - public Long getId() { - return id; - } } diff --git a/src/main/java/camp/woowak/lab/menu/repository/MenuRepository.java b/src/main/java/camp/woowak/lab/menu/repository/MenuRepository.java index a1de78e7..7ee862bd 100644 --- a/src/main/java/camp/woowak/lab/menu/repository/MenuRepository.java +++ b/src/main/java/camp/woowak/lab/menu/repository/MenuRepository.java @@ -18,4 +18,6 @@ public interface MenuRepository extends JpaRepository { @Lock(LockModeType.PESSIMISTIC_WRITE) @Query("SELECT m FROM Menu m where m.id in :ids") List findAllByIdForUpdate(List ids); + + List findByStoreId(Long storeId); } diff --git a/src/main/java/camp/woowak/lab/order/service/dto/OrderDTO.java b/src/main/java/camp/woowak/lab/order/service/dto/OrderDTO.java index 83cf548e..bb7d3a1d 100644 --- a/src/main/java/camp/woowak/lab/order/service/dto/OrderDTO.java +++ b/src/main/java/camp/woowak/lab/order/service/dto/OrderDTO.java @@ -72,7 +72,7 @@ public StoreDTO(Store store) { this.id = store.getId(); this.name = store.getName(); this.ownerName = store.getOwner().getName(); - this.address = store.getStoreAddress().getDistrict(); + this.address = store.getStoreAddress(); this.phoneNumber = store.getPhoneNumber(); } } diff --git a/src/main/java/camp/woowak/lab/store/domain/Store.java b/src/main/java/camp/woowak/lab/store/domain/Store.java index 2fa57146..0aac748e 100644 --- a/src/main/java/camp/woowak/lab/store/domain/Store.java +++ b/src/main/java/camp/woowak/lab/store/domain/Store.java @@ -1,6 +1,7 @@ package camp.woowak.lab.store.domain; import java.time.LocalDateTime; +import java.time.LocalTime; import java.util.UUID; import camp.woowak.lab.store.exception.NotEqualsOwnerException; @@ -81,4 +82,33 @@ public boolean isOpen() { return (now.isEqual(openTime) || now.isAfter(openTime)) && now.isBefore(closeTime); } + + public String getStoreAddress() { + return storeAddress.getDistrict(); + } + + public Long getStoreCategoryId() { + return storeCategory.getId(); + } + + public String getStoreCategoryName() { + return storeCategory.getName(); + } + + public LocalTime getStoreStartTime() { + return storeTime.getStartTime().toLocalTime(); + } + + public LocalTime getStoreEndTime() { + return storeTime.getEndTime().toLocalTime(); + } + + public UUID getVendorId() { + return owner.getId(); + } + + public String getVendorName() { + return owner.getName(); + } + } diff --git a/src/main/java/camp/woowak/lab/store/domain/StoreAddress.java b/src/main/java/camp/woowak/lab/store/domain/StoreAddress.java index bcb35f3e..b876fcb0 100644 --- a/src/main/java/camp/woowak/lab/store/domain/StoreAddress.java +++ b/src/main/java/camp/woowak/lab/store/domain/StoreAddress.java @@ -20,4 +20,7 @@ public StoreAddress(final String district) { this.district = district; } + public String getDistrict() { + return district; + } } diff --git a/src/main/java/camp/woowak/lab/store/service/StoreDisplayService.java b/src/main/java/camp/woowak/lab/store/service/StoreDisplayService.java new file mode 100644 index 00000000..f82f5bab --- /dev/null +++ b/src/main/java/camp/woowak/lab/store/service/StoreDisplayService.java @@ -0,0 +1,46 @@ +package camp.woowak.lab.store.service; + +import java.util.List; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import camp.woowak.lab.menu.domain.Menu; +import camp.woowak.lab.menu.repository.MenuRepository; +import camp.woowak.lab.store.domain.Store; +import camp.woowak.lab.store.exception.NotFoundStoreException; +import camp.woowak.lab.store.repository.StoreRepository; +import camp.woowak.lab.store.service.response.StoreDisplayResponse; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class StoreDisplayService { + + private final StoreRepository storeRepository; + private final MenuRepository menuRepository; + + @Transactional(readOnly = true) + public StoreDisplayResponse displayStore(final Long storeId) { + Store store = findStoreById(storeId); + List storeMenus = findMenusByStore(store.getId()); + + return StoreDisplayResponse.of(store, mapFrom(storeMenus)); + } + + private Store findStoreById(final Long storeId) { + return storeRepository.findById(storeId) + .orElseThrow(() -> new NotFoundStoreException(storeId + "의 가게를 찾을 수 없습니다.")); + } + + private List findMenusByStore(final Long storeId) { + return menuRepository.findByStoreId(storeId); + } + + private List mapFrom(final List menus) { + return menus.stream() + .map(StoreDisplayResponse.MenuDisplayResponse::of) + .toList(); + } + +} diff --git a/src/main/java/camp/woowak/lab/store/service/response/StoreDisplayResponse.java b/src/main/java/camp/woowak/lab/store/service/response/StoreDisplayResponse.java new file mode 100644 index 00000000..5894a6b5 --- /dev/null +++ b/src/main/java/camp/woowak/lab/store/service/response/StoreDisplayResponse.java @@ -0,0 +1,70 @@ +package camp.woowak.lab.store.service.response; + +import java.time.LocalTime; +import java.util.List; +import java.util.UUID; + +import camp.woowak.lab.menu.domain.Menu; +import camp.woowak.lab.store.domain.Store; + +public record StoreDisplayResponse( + + Long storeId, + String storeName, + String storeAddress, + String storePhoneNumber, + Integer storeMinOrderPrice, + + Long storeCategoryId, + String storeCategoryName, + + LocalTime storeStartTime, + LocalTime storeEndTime, + + UUID vendorId, + String vendorName, + + List menus +) { + + public static StoreDisplayResponse of(final Store store, final List menus) { + return new StoreDisplayResponse( + store.getId(), + store.getName(), + store.getStoreAddress(), + store.getPhoneNumber(), + store.getMinOrderPrice(), + + store.getStoreCategoryId(), + store.getStoreCategoryName(), + + store.getStoreStartTime(), + store.getStoreEndTime(), + + store.getVendorId(), + store.getVendorName(), + menus + ); + } + + public record MenuDisplayResponse( + Long menuCategoryId, + String menuCategoryName, + + Long menuId, + String menuName, + Long menuPrice + ) { + + public static MenuDisplayResponse of(final Menu menu) { + return new MenuDisplayResponse( + menu.getMenuCategoryId(), + menu.getMenuCategoryName(), + + menu.getId(), + menu.getName(), + menu.getPrice() + ); + } + } +} diff --git a/src/main/java/camp/woowak/lab/web/api/store/StoreApiController.java b/src/main/java/camp/woowak/lab/web/api/store/StoreApiController.java index 075ff8cd..2faaa8a9 100644 --- a/src/main/java/camp/woowak/lab/web/api/store/StoreApiController.java +++ b/src/main/java/camp/woowak/lab/web/api/store/StoreApiController.java @@ -2,6 +2,7 @@ import java.util.List; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PatchMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -13,11 +14,13 @@ import camp.woowak.lab.menu.service.MenuCategoryRegistrationService; import camp.woowak.lab.menu.service.MenuPriceUpdateService; import camp.woowak.lab.menu.service.command.MenuCategoryRegistrationCommand; +import camp.woowak.lab.store.service.StoreDisplayService; import camp.woowak.lab.menu.service.command.MenuPriceUpdateCommand; import camp.woowak.lab.store.service.StoreMenuRegistrationService; import camp.woowak.lab.store.service.StoreRegistrationService; import camp.woowak.lab.store.service.command.StoreMenuRegistrationCommand; import camp.woowak.lab.store.service.command.StoreRegistrationCommand; +import camp.woowak.lab.store.service.response.StoreDisplayResponse; import camp.woowak.lab.web.authentication.LoginVendor; import camp.woowak.lab.web.authentication.annotation.AuthenticationPrincipal; import camp.woowak.lab.web.dao.store.StoreDao; @@ -43,6 +46,7 @@ public class StoreApiController { private final MenuCategoryRegistrationService menuCategoryRegistrationService; private final MenuPriceUpdateService menuPriceUpdateService; private final StoreDao storeDao; + private final StoreDisplayService storeDisplayService; @GetMapping("/stores") public StoreInfoListResponse getStoreInfos( @@ -111,4 +115,8 @@ public MenuCategoryRegistrationResponse storeCategoryRegistration(@Authenticatio return new MenuCategoryRegistrationResponse(registeredId); } + @GetMapping("/stores/{storeId}") + public StoreDisplayResponse storeDisplay(@PathVariable Long storeId) { + return storeDisplayService.displayStore(storeId); + } } diff --git a/src/test/java/camp/woowak/lab/store/service/StoreDisplayServiceTest.java b/src/test/java/camp/woowak/lab/store/service/StoreDisplayServiceTest.java new file mode 100644 index 00000000..7807adfa --- /dev/null +++ b/src/test/java/camp/woowak/lab/store/service/StoreDisplayServiceTest.java @@ -0,0 +1,158 @@ +package camp.woowak.lab.store.service; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.BDDMockito.*; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Optional; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import camp.woowak.lab.menu.domain.Menu; +import camp.woowak.lab.menu.domain.MenuCategory; +import camp.woowak.lab.menu.repository.MenuRepository; +import camp.woowak.lab.payaccount.domain.PayAccount; +import camp.woowak.lab.payaccount.domain.TestPayAccount; +import camp.woowak.lab.store.domain.Store; +import camp.woowak.lab.store.domain.StoreAddress; +import camp.woowak.lab.store.domain.StoreCategory; +import camp.woowak.lab.store.repository.StoreRepository; +import camp.woowak.lab.store.service.response.StoreDisplayResponse; +import camp.woowak.lab.vendor.domain.Vendor; +import camp.woowak.lab.web.authentication.NoOpPasswordEncoder; +import camp.woowak.lab.web.authentication.PasswordEncoder; + +@ExtendWith(MockitoExtension.class) +class StoreDisplayServiceTest { + + @InjectMocks + private StoreDisplayService storeDisplayService; + + @Mock + private StoreRepository storeRepository; + + @Mock + private MenuRepository menuRepository; + + @Nested + @DisplayName("매장을 전시하는 기능은") + class DisplayStoreTest { + + Vendor vendor; + StoreCategory storeCategory; + Store store; + MenuCategory menuCategory; + Menu menu1; + Menu menu2; + + @Test + @DisplayName("[Success] 매장 정보, 매장 카테고리 정보, 매장 메뉴 정보를 ResponseDTO 에 매핑하여 응답한다") + void test() { + // given + long storeId = 1L; + setup(storeId); + given(storeRepository.findById(storeId)).willReturn(Optional.of(store)); + given(menuRepository.findByStoreId(storeId)).willReturn(List.of(menu1, menu2)); + + // when + StoreDisplayResponse response = storeDisplayService.displayStore(storeId); + + // then + assertStore(response, storeId); + assertStoreCategory(response); + assertMenu(response); + } + + private void assertStore(StoreDisplayResponse response, long storeId) { + assertThat(response.storeId()).isEqualTo(storeId); + assertThat(response.storeName()).isEqualTo(store.getName()); + assertThat(response.storeAddress()).isEqualTo(store.getStoreAddress()); + assertThat(response.storePhoneNumber()).isEqualTo(store.getPhoneNumber()); + assertThat(response.storeMinOrderPrice()).isEqualTo(store.getMinOrderPrice()); + assertThat(response.storeStartTime()).isEqualTo(store.getStoreStartTime()); + assertThat(response.storeEndTime()).isEqualTo(store.getStoreEndTime()); + } + + private void assertStoreCategory(StoreDisplayResponse response) { + assertThat(response.storeCategoryId()).isEqualTo(storeCategory.getId()); + assertThat(response.storeCategoryName()).isEqualTo(storeCategory.getName()); + } + + private void assertMenu(StoreDisplayResponse response) { + assertThat(response.menus()).hasSize(2); + assertThat(response.menus()).extracting("menuCategoryId").containsOnly(menuCategory.getId()); + assertThat(response.menus()).extracting("menuCategoryName").containsOnly(menuCategory.getName()); + assertThat(response.menus()).extracting("menuId").containsExactlyInAnyOrder(menu1.getId(), menu2.getId()); + assertThat(response.menus()).extracting("menuName").containsExactlyInAnyOrder("후라이드치킨", "양념치킨"); + } + + private void setup(long storeId) { + vendor = createVendor(); + storeCategory = createStoreCategory(); + store = createValidStore(storeId, vendor, storeCategory); + menuCategory = createMenuCategory(store); + menu1 = createMenu(store, menuCategory, "후라이드치킨"); + menu2 = createMenu(store, menuCategory, "양념치킨"); + } + + private Store createValidStore(Long id, Vendor vendor, StoreCategory storeCategory) { + LocalDateTime validStartDateFixture = LocalDateTime.of(2020, 1, 1, 1, 1); + LocalDateTime validEndDateFixture = LocalDateTime.of(2020, 1, 1, 2, 1); + String validNameFixture = "3K1K 가게"; + String validAddressFixture = StoreAddress.DEFAULT_DISTRICT; + String validPhoneNumberFixture = "02-1234-5678"; + Integer validMinOrderPriceFixture = 5000; + + return new TestStore(id, vendor, storeCategory, validNameFixture, validAddressFixture, + validPhoneNumberFixture, + validMinOrderPriceFixture, validStartDateFixture, validEndDateFixture); + } + + private Vendor createVendor() { + String name = "vendor"; + String email = "validEmail@validEmail.com"; + String password = "validPassword"; + String phone = "010-0000-0000"; + PayAccount payAccount = new TestPayAccount(1L); + PasswordEncoder passwordEncoder = new NoOpPasswordEncoder(); + + return new Vendor(name, email, password, phone, payAccount, passwordEncoder); + } + + private StoreCategory createStoreCategory() { + return new StoreCategory("양식"); + } + + private MenuCategory createMenuCategory(Store store) { + return new MenuCategory(store, "치킨카테고리"); + } + + private Menu createMenu(Store store, MenuCategory menuCategory, String name) { + return new Menu(store, menuCategory, name, 10000L, 50L, "image"); + } + + } + + static class TestStore extends Store { + private final Long id; + + TestStore(Long id, Vendor vendor, StoreCategory storeCategory, String name, String address, String phoneNumber, + Integer minOrderPrice, LocalDateTime startTime, LocalDateTime endTime) { + super(vendor, storeCategory, name, address, phoneNumber, minOrderPrice, startTime, endTime); + this.id = id; + } + + @Override + public Long getId() { + return this.id; + } + } + +} \ No newline at end of file diff --git a/src/test/java/camp/woowak/lab/web/api/store/StoreApiControllerTest.java b/src/test/java/camp/woowak/lab/web/api/store/StoreApiControllerTest.java index fcfd2204..c4a5a08e 100644 --- a/src/test/java/camp/woowak/lab/web/api/store/StoreApiControllerTest.java +++ b/src/test/java/camp/woowak/lab/web/api/store/StoreApiControllerTest.java @@ -5,6 +5,8 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; import java.time.LocalDateTime; +import java.time.LocalTime; +import java.util.List; import java.util.Optional; import java.util.Random; import java.util.UUID; @@ -20,6 +22,8 @@ import org.springframework.data.jpa.mapping.JpaMetamodelMappingContext; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.ResultActions; +import org.springframework.test.web.servlet.result.MockMvcResultHandlers; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; @@ -35,9 +39,11 @@ import camp.woowak.lab.payaccount.domain.PayAccount; import camp.woowak.lab.payaccount.domain.TestPayAccount; import camp.woowak.lab.store.exception.NotFoundStoreCategoryException; +import camp.woowak.lab.store.service.StoreDisplayService; import camp.woowak.lab.store.service.StoreMenuRegistrationService; import camp.woowak.lab.store.service.StoreRegistrationService; import camp.woowak.lab.store.service.command.StoreRegistrationCommand; +import camp.woowak.lab.store.service.response.StoreDisplayResponse; import camp.woowak.lab.vendor.domain.Vendor; import camp.woowak.lab.vendor.repository.VendorRepository; import camp.woowak.lab.web.authentication.AuthenticationErrorCode; @@ -79,6 +85,9 @@ class StoreApiControllerTest { @MockBean private MenuPriceUpdateService menuPriceUpdateService; + @MockBean + private StoreDisplayService storeDisplayService; + DateTimeProvider fixedStartTime = () -> LocalDateTime.of(2024, 8, 24, 1, 0, 0); DateTimeProvider fixedEndTime = () -> LocalDateTime.of(2024, 8, 24, 5, 0, 0); @@ -258,6 +267,80 @@ void failWith403() throws Exception { } } + @Nested + @DisplayName("매장 전시: GET /stores/{storeId}") + class StoreDisplayTest { + + @Test + public void testStoreDisplay() throws Exception { + // Given + Long storeId = 1L; + String storeName = "Test Store"; + String storeAddress = "123 Test St"; + int storeMinOrderPrice = 10000; + long storeCategoryId = 1L; + String storePhoneNumber = "123-456-7890"; + String storeCategoryName = "Test Category"; + String vendorName = "Test Vendor"; + + long menuCategoryId = 1L; + String menuCategoryName = "Test Menu Category"; + long menuId = 1L; + String menName = "Test Menu"; + long menuPrice = 15000; + + List menuDisplayResponses = List.of( + new StoreDisplayResponse.MenuDisplayResponse( + menuCategoryId, + menuCategoryName, + menuId, + menName, + menuPrice + )); + StoreDisplayResponse mockResponse = new StoreDisplayResponse( + storeId, + storeName, + storeAddress, + storePhoneNumber, + storeMinOrderPrice, + storeCategoryId, + storeCategoryName, + LocalTime.of(9, 0), + LocalTime.of(22, 0), + UUID.randomUUID(), + vendorName, + menuDisplayResponses + ); + given(storeDisplayService.displayStore(storeId)).willReturn(mockResponse); + + // When & Then + ResultActions resultActions = mockMvc.perform(get("/stores/{storeId}", storeId)) + .andDo(MockMvcResultHandlers.print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.data.storeId").value(storeId)) + .andExpect(jsonPath("$.data.storeName").value(storeName)) + .andExpect(jsonPath("$.data.storeAddress").value(storeAddress)) + .andExpect(jsonPath("$.data.storePhoneNumber").value(storePhoneNumber)) + .andExpect(jsonPath("$.data.storeMinOrderPrice").value(storeMinOrderPrice)) + .andExpect(jsonPath("$.data.storeCategoryId").value(1)) + .andExpect(jsonPath("$.data.storeCategoryName").value(storeCategoryName)) + .andExpect(jsonPath("$.data.storeStartTime").value("09:00:00")) + .andExpect(jsonPath("$.data.storeEndTime").value("22:00:00")) + .andExpect(jsonPath("$.data.vendorName").value(vendorName)); + + // 메뉴 리스트 검증 + for (int i = 0; i < menuDisplayResponses.size(); i++) { + StoreDisplayResponse.MenuDisplayResponse menu = menuDisplayResponses.get(i); + resultActions + .andExpect(jsonPath("$.data.menus[" + i + "].menuCategoryId").value(menu.menuCategoryId())) + .andExpect(jsonPath("$.data.menus[" + i + "].menuCategoryName").value(menu.menuCategoryName())) + .andExpect(jsonPath("$.data.menus[" + i + "].menuId").value(menu.menuId())) + .andExpect(jsonPath("$.data.menus[" + i + "].menuName").value(menu.menuName())) + .andExpect(jsonPath("$.data.menus[" + i + "].menuPrice").value(menu.menuPrice())); + } + } + } + @Nested @DisplayName("메뉴 가격 수정 : PUT /stores/menus/{menuId}/price") class MenuPriceUpdate {