diff --git a/src/main/java/io/beaniejoy/dongnecafe/domain/cafe/controller/CafeController.kt b/src/main/java/io/beaniejoy/dongnecafe/domain/cafe/controller/CafeController.kt index d9dbfee..21b2f2f 100644 --- a/src/main/java/io/beaniejoy/dongnecafe/domain/cafe/controller/CafeController.kt +++ b/src/main/java/io/beaniejoy/dongnecafe/domain/cafe/controller/CafeController.kt @@ -27,7 +27,7 @@ class CafeController( } @GetMapping - fun searchCafeList( + fun searchCafe( @PageableDefault(sort = ["name"], direction = Sort.Direction.ASC, page = 0, size = 10) pageable: Pageable ): Page { return cafeService.getCafeList(pageable) diff --git a/src/main/java/io/beaniejoy/dongnecafe/domain/cafe/entity/Cafe.kt b/src/main/java/io/beaniejoy/dongnecafe/domain/cafe/entity/Cafe.kt index 41d6442..bd694fb 100644 --- a/src/main/java/io/beaniejoy/dongnecafe/domain/cafe/entity/Cafe.kt +++ b/src/main/java/io/beaniejoy/dongnecafe/domain/cafe/entity/Cafe.kt @@ -49,21 +49,11 @@ class Cafe protected constructor( description: String, cafeMenuRequestList: List, ): Cafe { - val cafeMenuList = cafeMenuRequestList.map { cafeMenuRequestDto -> + val cafeMenuEntityList = cafeMenuRequestList.map { cafeMenuRequestDto -> CafeMenu.createCafeMenu( name = cafeMenuRequestDto.name!!, price = cafeMenuRequestDto.price, - menuOptionList = cafeMenuRequestDto.menuOptionList.map { menuOptionRequestDto -> - MenuOption.createMenuOption( - title = menuOptionRequestDto.title, - optionDetailList = menuOptionRequestDto.optionDetailList.map { optionDetailRequestDto -> - OptionDetail.createOptionDetail( - name = optionDetailRequestDto.name, - extraPrice = optionDetailRequestDto.extraPrice - ) - } - ) - } + menuOptionRequestList = cafeMenuRequestDto.menuOptionList ) } @@ -73,7 +63,7 @@ class Cafe protected constructor( phoneNumber = phoneNumber, description = description ).apply { - cafeMenuList.forEach { this.addCafeMenu(it) } + cafeMenuEntityList.forEach { this.addCafeMenu(it) } } } } diff --git a/src/main/java/io/beaniejoy/dongnecafe/domain/cafe/entity/CafeMenu.kt b/src/main/java/io/beaniejoy/dongnecafe/domain/cafe/entity/CafeMenu.kt index bf943cf..ed9d00d 100644 --- a/src/main/java/io/beaniejoy/dongnecafe/domain/cafe/entity/CafeMenu.kt +++ b/src/main/java/io/beaniejoy/dongnecafe/domain/cafe/entity/CafeMenu.kt @@ -1,6 +1,7 @@ package io.beaniejoy.dongnecafe.domain.cafe.entity import io.beaniejoy.dongnecafe.common.entity.BaseTimeEntity +import io.beaniejoy.dongnecafe.domain.cafe.dto.request.MenuOptionInfoRequestDto import java.math.BigDecimal import javax.persistence.* @@ -29,12 +30,19 @@ class CafeMenu protected constructor( val menuOptionList: MutableList = arrayListOf() companion object { - fun createCafeMenu(name: String, price: BigDecimal, menuOptionList: List): CafeMenu { + fun createCafeMenu(name: String, price: BigDecimal, menuOptionRequestList: List): CafeMenu { + val menuOptionEntityList = menuOptionRequestList.map { menuOptionRequestDto -> + MenuOption.createMenuOption( + title = menuOptionRequestDto.title, + optionDetailRequestList = menuOptionRequestDto.optionDetailList + ) + } + return CafeMenu( name = name, price = price ).apply { - menuOptionList.forEach { this.addMenuOption(it) } + menuOptionEntityList.forEach { this.addMenuOption(it) } } } } diff --git a/src/main/java/io/beaniejoy/dongnecafe/domain/cafe/entity/MenuOption.kt b/src/main/java/io/beaniejoy/dongnecafe/domain/cafe/entity/MenuOption.kt index 37938fd..ac18c11 100644 --- a/src/main/java/io/beaniejoy/dongnecafe/domain/cafe/entity/MenuOption.kt +++ b/src/main/java/io/beaniejoy/dongnecafe/domain/cafe/entity/MenuOption.kt @@ -1,6 +1,7 @@ package io.beaniejoy.dongnecafe.domain.cafe.entity import io.beaniejoy.dongnecafe.common.entity.BaseTimeEntity +import io.beaniejoy.dongnecafe.domain.cafe.dto.request.OptionDetailInfoRequestDto import javax.persistence.* @Entity @@ -24,11 +25,18 @@ class MenuOption protected constructor( val optionDetailList: MutableList = arrayListOf() companion object { - fun createMenuOption(title: String, optionDetailList: List): MenuOption { + fun createMenuOption(title: String, optionDetailRequestList: List): MenuOption { + val optionDetailEntityList = optionDetailRequestList.map { optionDetailRequestDto -> + OptionDetail.createOptionDetail( + name = optionDetailRequestDto.name, + extraPrice = optionDetailRequestDto.extraPrice + ) + } + return MenuOption( title = title ).apply { - optionDetailList.forEach { this.addOptionDetail(it) } + optionDetailEntityList.forEach { this.addOptionDetail(it) } } } } diff --git a/src/main/java/io/beaniejoy/dongnecafe/domain/cafe/service/CafeService.kt b/src/main/java/io/beaniejoy/dongnecafe/domain/cafe/service/CafeService.kt index 2f5c80c..c3563df 100644 --- a/src/main/java/io/beaniejoy/dongnecafe/domain/cafe/service/CafeService.kt +++ b/src/main/java/io/beaniejoy/dongnecafe/domain/cafe/service/CafeService.kt @@ -32,6 +32,7 @@ class CafeService( * - 메뉴 옵션 (옵션 이름 /ex. 사이즈) * - 옵션 상세 (상세 이름, 추가 금액 /ex. [(medium, 0), (large, 200), (venti, 700)]) */ + @Transactional fun createCafe( name: String, address: String, diff --git a/src/test/java/io/beaniejoy/dongnecafe/domain/cafe/entity/CafeTest.kt b/src/test/java/io/beaniejoy/dongnecafe/domain/cafe/entity/CafeTest.kt new file mode 100644 index 0000000..70349f3 --- /dev/null +++ b/src/test/java/io/beaniejoy/dongnecafe/domain/cafe/entity/CafeTest.kt @@ -0,0 +1,106 @@ +package io.beaniejoy.dongnecafe.domain.cafe.entity + +import io.beaniejoy.dongnecafe.domain.cafe.dto.request.CafeInfoRequestDto +import io.beaniejoy.dongnecafe.domain.cafe.dto.request.CafeMenuInfoRequestDto +import io.beaniejoy.dongnecafe.domain.cafe.dto.request.MenuOptionInfoRequestDto +import io.beaniejoy.dongnecafe.domain.cafe.dto.request.OptionDetailInfoRequestDto +import org.junit.jupiter.api.Assertions.* +import org.junit.jupiter.api.Test +import java.math.BigDecimal + +internal class CafeTest { + @Test + fun create_cafe_test() { + val cafeRequestDto = createCreateCafeRequestDto() + + val cafe = Cafe.createCafe( + name = cafeRequestDto.name!!, + address = cafeRequestDto.address!!, + phoneNumber = cafeRequestDto.phoneNumber!!, + description = cafeRequestDto.description!!, + cafeMenuRequestList = cafeRequestDto.cafeMenuList + ) + + assertEquals(cafeRequestDto.name, cafe.name) + assertEquals(cafeRequestDto.address, cafe.address) + assertEquals(cafeRequestDto.phoneNumber, cafe.phoneNumber) + assertEquals(cafeRequestDto.description, cafe.description) + + assertCafeMenuListEquals(cafeRequestDto.cafeMenuList, cafe.cafeMenuList) + } + + private fun assertCafeMenuListEquals( + cafeMenuRequestList: List, + cafeMenuList: List, + ) { + for (index in cafeMenuRequestList.indices) { + assertEquals(cafeMenuRequestList[index].name, cafeMenuList[index].name) + assertEquals(cafeMenuRequestList[index].price, cafeMenuList[index].price) + + assertMenuOptionListEquals(cafeMenuRequestList[index].menuOptionList, cafeMenuList[index].menuOptionList) + } + } + + private fun assertMenuOptionListEquals( + menuOptionRequestList: List, + menuOptionList: List, + ) { + for (index in menuOptionRequestList.indices) { + assertEquals(menuOptionRequestList[index].title, menuOptionList[index].title) + + assertOptionDetailListEquals( + menuOptionRequestList[index].optionDetailList, + menuOptionList[index].optionDetailList + ) + } + } + + private fun assertOptionDetailListEquals( + optionDetailRequestList: List, + optionDetailList: MutableList, + ) { + for (index in optionDetailRequestList.indices) { + assertEquals(optionDetailRequestList[index].name, optionDetailList[index].name) + assertEquals(optionDetailRequestList[index].extraPrice, optionDetailList[index].extraPrice) + + } + } + + private fun createCreateCafeRequestDto(): CafeInfoRequestDto { + val cafeName = "beanie_cafe" + val cafeAddress = "beanie_cafe_address" + val phoneNumber = "01012345678" + val description = "beanie_cafe_description" + + val sizeOptionDetailList = listOf( + OptionDetailInfoRequestDto(name = "medium", extraPrice = BigDecimal.ZERO), + OptionDetailInfoRequestDto(name = "large", extraPrice = BigDecimal.valueOf(200L)), + OptionDetailInfoRequestDto(name = "venti", extraPrice = BigDecimal.valueOf(700L)) + ) + val sizeMenuOption = MenuOptionInfoRequestDto( + title = "size", + optionDetailList = sizeOptionDetailList + ) + + val cafeMenuList = listOf( + CafeMenuInfoRequestDto( + name = "menu1", + price = BigDecimal.valueOf(2_800L), + menuOptionList = listOf(sizeMenuOption) + ), + CafeMenuInfoRequestDto( + name = "menu2", + price = BigDecimal.valueOf(3_500L), + menuOptionList = listOf(sizeMenuOption) + ), + ) + + return CafeInfoRequestDto( + name = cafeName, + address = cafeAddress, + phoneNumber = phoneNumber, + description = description, + cafeMenuList = cafeMenuList + ) + } +} \ No newline at end of file diff --git a/src/test/java/io/beaniejoy/dongnecafe/domain/cafe/service/CafeServiceMockTest.kt b/src/test/java/io/beaniejoy/dongnecafe/domain/cafe/service/CafeServiceMockTest.kt new file mode 100644 index 0000000..cf85768 --- /dev/null +++ b/src/test/java/io/beaniejoy/dongnecafe/domain/cafe/service/CafeServiceMockTest.kt @@ -0,0 +1,193 @@ +package io.beaniejoy.dongnecafe.domain.cafe.service + +import io.beaniejoy.dongnecafe.domain.cafe.dto.request.CafeInfoRequestDto +import io.beaniejoy.dongnecafe.domain.cafe.dto.request.CafeMenuInfoRequestDto +import io.beaniejoy.dongnecafe.domain.cafe.dto.request.MenuOptionInfoRequestDto +import io.beaniejoy.dongnecafe.domain.cafe.dto.request.OptionDetailInfoRequestDto +import io.beaniejoy.dongnecafe.domain.cafe.entity.Cafe +import io.beaniejoy.dongnecafe.domain.cafe.error.CafeExistedException +import io.beaniejoy.dongnecafe.domain.cafe.error.CafeNotFoundException +import io.beaniejoy.dongnecafe.domain.cafe.repository.CafeRepository +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.MethodOrderer +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestMethodOrder +import org.junit.jupiter.api.assertThrows +import org.junit.jupiter.api.extension.ExtendWith +import org.mockito.InjectMocks +import org.mockito.Mock +import org.mockito.Mockito.* +import org.mockito.junit.jupiter.MockitoExtension +import java.math.BigDecimal +import java.util.* +import javax.persistence.GeneratedValue + +@ExtendWith(MockitoExtension::class) +@TestMethodOrder(MethodOrderer.DisplayName::class) +internal class CafeServiceMockTest { + @InjectMocks + lateinit var mockCafeService: CafeService + + @Mock + lateinit var mockCafeRepository: CafeRepository + + @Test + @DisplayName("카페 신규 생성 테스트") + fun create_cafe_test() { + // given + val cafeRequestDto = createCreateCafeRequestDto() + val savedMockCafeId = 100L + + `when`(mockCafeRepository.findByName(cafeRequestDto.name!!)).thenReturn(null) + `when`(mockCafeRepository.save(any(Cafe::class.java))).thenAnswer { + injectCafeId(it.getArgument(0), savedMockCafeId) + } + + // when + val savedCafeId = mockCafeService.createCafe( + name = cafeRequestDto.name!!, + address = cafeRequestDto.address!!, + phoneNumber = cafeRequestDto.phoneNumber!!, + description = cafeRequestDto.description!!, + cafeMenuRequestList = cafeRequestDto.cafeMenuList + ) + + // then + verify(mockCafeRepository).findByName(cafeRequestDto.name!!) // TODO eq 에러 발생 이유 + verify(mockCafeRepository).save(any(Cafe::class.java)) + + assertEquals(savedCafeId, savedMockCafeId) + } + + @Test + @DisplayName("카페 신규 생성시 이미 존재하는 카페 예외 발생 테스트") + fun fail_create_cafe_when_existed() { + // given + val cafeRequestDto = createCreateCafeRequestDto() + val cafe = Cafe.createCafe( + name = cafeRequestDto.name!!, + address = cafeRequestDto.address!!, + phoneNumber = cafeRequestDto.phoneNumber!!, + description = cafeRequestDto.description!!, + cafeMenuRequestList = cafeRequestDto.cafeMenuList + ) + + `when`(mockCafeRepository.findByName(cafeRequestDto.name!!)).thenReturn(cafe) + + // then + assertThrows { + // when + mockCafeService.createCafe( + name = cafeRequestDto.name!!, + address = cafeRequestDto.address!!, + phoneNumber = cafeRequestDto.phoneNumber!!, + description = cafeRequestDto.description!!, + cafeMenuRequestList = cafeRequestDto.cafeMenuList + ) + } + } + + @Test + @DisplayName("카페 정보 변경 테스트") + fun update_cafe_test() { + // given + val cafeRequestDto = createCreateCafeRequestDto() + val cafe = Cafe.createCafe( + name = cafeRequestDto.name!!, + address = cafeRequestDto.address!!, + phoneNumber = cafeRequestDto.phoneNumber!!, + description = cafeRequestDto.description!!, + cafeMenuRequestList = cafeRequestDto.cafeMenuList + ) + val cafeId = 50L + + // TODO findByIdOrNull은 kotlin test 라이브러리 필요한 듯 + `when`(mockCafeRepository.findById(cafeId)).thenReturn(Optional.of(cafe)) + + // then + mockCafeService.updateCafe( + id = cafeId, + name = "", + address = "", + phoneNumber = "", + description = "", + ) + + verify(mockCafeRepository).findById(eq(cafeId)) + + // TODO update TEST 방법? + } + + @Test + @DisplayName("카페 정보 변경시 존재하지 않는 카페 예외 발생 테스트") + fun fail_update_cafe_when_not_found() { + // given + val cafeId = 50L + + `when`(mockCafeRepository.findById(cafeId)).thenReturn(Optional.empty()) + + assertThrows { + mockCafeService.updateCafe( + id = cafeId, + name = "", + address = "", + phoneNumber = "", + description = "", + ) + } + } + + private fun createCreateCafeRequestDto(): CafeInfoRequestDto { + val cafeName = "beanie_cafe" + val cafeAddress = "beanie_cafe_address" + val phoneNumber = "01012345678" + val description = "beanie_cafe_description" + + val sizeOptionDetailList = listOf( + OptionDetailInfoRequestDto(name = "medium", extraPrice = BigDecimal.ZERO), + OptionDetailInfoRequestDto(name = "large", extraPrice = BigDecimal.valueOf(200L)), + OptionDetailInfoRequestDto(name = "venti", extraPrice = BigDecimal.valueOf(700L)) + ) + val sizeMenuOption = MenuOptionInfoRequestDto( + title = "size", + optionDetailList = sizeOptionDetailList + ) + + val cafeMenuList = listOf( + CafeMenuInfoRequestDto( + name = "menu1", + price = BigDecimal.valueOf(2_800L), + menuOptionList = listOf(sizeMenuOption) + ), + CafeMenuInfoRequestDto( + name = "menu2", + price = BigDecimal.valueOf(3_500L), + menuOptionList = listOf(sizeMenuOption) + ), + ) + + return CafeInfoRequestDto( + name = cafeName, + address = cafeAddress, + phoneNumber = phoneNumber, + description = description, + cafeMenuList = cafeMenuList + ) + } + + private fun injectCafeId( + cafe: Cafe, + newCafeId: Long, + ): Cafe { + val idField = cafe.javaClass.declaredFields + .find { f -> + f.getAnnotation(GeneratedValue::class.java) != null + } ?: return cafe + + idField.isAccessible = true + idField.set(cafe, newCafeId) + + return cafe + } +} \ No newline at end of file diff --git a/src/test/java/io/beaniejoy/dongnecafe/domain/cafe/service/CafeServiceTest.kt b/src/test/java/io/beaniejoy/dongnecafe/domain/cafe/service/CafeServiceTest.kt index e9a4d81..ccd834b 100644 --- a/src/test/java/io/beaniejoy/dongnecafe/domain/cafe/service/CafeServiceTest.kt +++ b/src/test/java/io/beaniejoy/dongnecafe/domain/cafe/service/CafeServiceTest.kt @@ -1,193 +1,5 @@ package io.beaniejoy.dongnecafe.domain.cafe.service -import io.beaniejoy.dongnecafe.domain.cafe.dto.request.CafeInfoRequestDto -import io.beaniejoy.dongnecafe.domain.cafe.dto.request.CafeMenuInfoRequestDto -import io.beaniejoy.dongnecafe.domain.cafe.dto.request.MenuOptionInfoRequestDto -import io.beaniejoy.dongnecafe.domain.cafe.dto.request.OptionDetailInfoRequestDto -import io.beaniejoy.dongnecafe.domain.cafe.entity.Cafe -import io.beaniejoy.dongnecafe.domain.cafe.error.CafeExistedException -import io.beaniejoy.dongnecafe.domain.cafe.error.CafeNotFoundException -import io.beaniejoy.dongnecafe.domain.cafe.repository.CafeRepository -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.DisplayName -import org.junit.jupiter.api.MethodOrderer -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.TestMethodOrder -import org.junit.jupiter.api.assertThrows -import org.junit.jupiter.api.extension.ExtendWith -import org.mockito.InjectMocks -import org.mockito.Mock -import org.mockito.Mockito.* -import org.mockito.junit.jupiter.MockitoExtension -import java.math.BigDecimal -import java.util.* -import javax.persistence.GeneratedValue - -@ExtendWith(MockitoExtension::class) -@TestMethodOrder(MethodOrderer.DisplayName::class) -internal class CafeServiceTest { - @InjectMocks - lateinit var mockCafeService: CafeService - - @Mock - lateinit var mockCafeRepository: CafeRepository - - @Test - @DisplayName("카페 신규 생성 테스트") - fun create_cafe_test() { - // given - val cafeRequestDto = createCreateCafeRequestDto() - val savedMockCafeId = 100L - - `when`(mockCafeRepository.findByName(cafeRequestDto.name!!)).thenReturn(null) - `when`(mockCafeRepository.save(any(Cafe::class.java))).thenAnswer { - injectCafeId(it.getArgument(0), savedMockCafeId) - } - - // when - val savedCafeId = mockCafeService.createCafe( - name = cafeRequestDto.name!!, - address = cafeRequestDto.address!!, - phoneNumber = cafeRequestDto.phoneNumber!!, - description = cafeRequestDto.description!!, - cafeMenuRequestList = cafeRequestDto.cafeMenuList - ) - - // then - verify(mockCafeRepository).findByName(cafeRequestDto.name!!) // TODO eq 에러 발생 이유 - verify(mockCafeRepository).save(any(Cafe::class.java)) - - assertEquals(savedCafeId, savedMockCafeId) - } - - @Test - @DisplayName("카페 신규 생성시 이미 존재하는 카페 예외 발생 테스트") - fun fail_create_cafe_when_existed() { - // given - val cafeRequestDto = createCreateCafeRequestDto() - val cafe = Cafe.createCafe( - name = cafeRequestDto.name!!, - address = cafeRequestDto.address!!, - phoneNumber = cafeRequestDto.phoneNumber!!, - description = cafeRequestDto.description!!, - cafeMenuRequestList = cafeRequestDto.cafeMenuList - ) - - `when`(mockCafeRepository.findByName(cafeRequestDto.name!!)).thenReturn(cafe) - - // then - assertThrows { - // when - mockCafeService.createCafe( - name = cafeRequestDto.name!!, - address = cafeRequestDto.address!!, - phoneNumber = cafeRequestDto.phoneNumber!!, - description = cafeRequestDto.description!!, - cafeMenuRequestList = cafeRequestDto.cafeMenuList - ) - } - } - - @Test - @DisplayName("카페 정보 변경 테스트") - fun update_cafe_test() { - // given - val cafeRequestDto = createCreateCafeRequestDto() - val cafe = Cafe.createCafe( - name = cafeRequestDto.name!!, - address = cafeRequestDto.address!!, - phoneNumber = cafeRequestDto.phoneNumber!!, - description = cafeRequestDto.description!!, - cafeMenuRequestList = cafeRequestDto.cafeMenuList - ) - val cafeId = 50L - - // TODO findByIdOrNull은 kotlin test 라이브러리 필요한 듯 - `when`(mockCafeRepository.findById(cafeId)).thenReturn(Optional.of(cafe)) - - // then - mockCafeService.updateCafe( - id = cafeId, - name = "", - address = "", - phoneNumber = "", - description = "", - ) - - verify(mockCafeRepository).findById(eq(cafeId)) - - // TODO update TEST 방법? - } - - @Test - @DisplayName("카페 정보 변경시 존재하지 않는 카페 예외 발생 테스트") - fun fail_update_cafe_when_not_found() { - // given - val cafeId = 50L - - `when`(mockCafeRepository.findById(cafeId)).thenReturn(Optional.empty()) - - assertThrows { - mockCafeService.updateCafe( - id = cafeId, - name = "", - address = "", - phoneNumber = "", - description = "", - ) - } - } - - private fun createCreateCafeRequestDto(): CafeInfoRequestDto { - val cafeName = "beanie_cafe" - val cafeAddress = "beanie_cafe_address" - val phoneNumber = "01012345678" - val description = "beanie_cafe_description" - - val sizeOptionDetailList = listOf( - OptionDetailInfoRequestDto(name = "medium", extraPrice = BigDecimal.ZERO), - OptionDetailInfoRequestDto(name = "large", extraPrice = BigDecimal.valueOf(200L)), - OptionDetailInfoRequestDto(name = "venti", extraPrice = BigDecimal.valueOf(700L)) - ) - val sizeMenuOption = MenuOptionInfoRequestDto( - title = "size", - optionDetailList = sizeOptionDetailList - ) - - val cafeMenuList = listOf( - CafeMenuInfoRequestDto( - name = "menu1", - price = BigDecimal.valueOf(2_800L), - menuOptionList = listOf(sizeMenuOption) - ), - CafeMenuInfoRequestDto( - name = "menu2", - price = BigDecimal.valueOf(3_500L), - menuOptionList = listOf(sizeMenuOption) - ), - ) - - return CafeInfoRequestDto( - name = cafeName, - address = cafeAddress, - phoneNumber = phoneNumber, - description = description, - cafeMenuList = cafeMenuList - ) - } - - private fun injectCafeId( - cafe: Cafe, - newCafeId: Long, - ): Cafe { - val idField = cafe.javaClass.declaredFields - .find { f -> - f.getAnnotation(GeneratedValue::class.java) != null - } ?: return cafe - - idField.isAccessible = true - idField.set(cafe, newCafeId) - - return cafe - } +// TODO spring jpa 연동 테스트 (h2 테스트 DB 사용) +class CafeServiceTest { } \ No newline at end of file