Skip to content

Commit

Permalink
[feature] menu api 구현 및 테스트 작성 (#31)
Browse files Browse the repository at this point in the history
  • Loading branch information
dojinyou authored Oct 15, 2023
1 parent f701f95 commit 2c852c7
Show file tree
Hide file tree
Showing 8 changed files with 278 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ class MenuCommandService(
private val repository: MenuRepository,
private val storeRepository: StoreRepository,
) {
fun create(command: MenuCreateCommand): Long {
val store = storeRepository.getReferenceById(command.storeId)
fun create(storeId: Long, command: MenuCreateCommand): Long {
val store = storeRepository.getReferenceById(storeId)

val menu = Menu(
name = command.name,
Expand All @@ -26,8 +26,8 @@ class MenuCommandService(
return repository.save(menu).id
}

fun update(command: MenuUpdateCommand) {
val menu = repository.getReferenceById(command.id).apply {
fun update(id: Long, command: MenuUpdateCommand) {
val menu = repository.getReferenceById(id).apply {
name = command.name
price = command.price
imageAddress = command.imageAddress
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.mjucow.eatda.domain.store.service.command.dto

data class MenuCreateCommand(
val storeId: Long,
val name: String,
val price: Int,
val imageAddress: String? = null,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.mjucow.eatda.domain.store.service.command.dto

data class MenuUpdateCommand(
val id: Long,
val name: String,
val price: Int,
val imageAddress: String? = null,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package com.mjucow.eatda.presentation.store

import com.mjucow.eatda.domain.store.service.command.MenuCommandService
import com.mjucow.eatda.domain.store.service.command.StoreCommandService
import com.mjucow.eatda.domain.store.service.command.dto.MenuCreateCommand
import com.mjucow.eatda.domain.store.service.command.dto.StoreCreateCommand
import com.mjucow.eatda.domain.store.service.command.dto.StoreUpdateCommand
import com.mjucow.eatda.domain.store.service.query.MenuQueryService
import com.mjucow.eatda.domain.store.service.query.StoreQueryService
import com.mjucow.eatda.domain.store.service.query.dto.MenuList
import com.mjucow.eatda.domain.store.service.query.dto.StoreDetailDto
import com.mjucow.eatda.domain.store.service.query.dto.StoreDto
import com.mjucow.eatda.presentation.common.ApiResponse
Expand All @@ -27,6 +31,8 @@ import org.springframework.web.bind.annotation.RestController
class StoreController(
val storeQueryService: StoreQueryService,
val storeCommandService: StoreCommandService,
val menuQueryService: MenuQueryService,
val menuCommandService: MenuCommandService,
) {

@PostMapping
Expand Down Expand Up @@ -65,4 +71,19 @@ class StoreController(
fun deleteById(@PathVariable("storeId") id: Long) {
storeCommandService.delete(id)
}

@GetMapping("/{storeId}/menu")
@ResponseStatus(HttpStatus.OK)
fun findAllMenu(@PathVariable("storeId") id: Long): ApiResponse<MenuList> {
return ApiResponse.success(menuQueryService.findAll(id))
}

@PostMapping("/{storeId}/menu")
@ResponseStatus(HttpStatus.CREATED)
fun createMenu(
@PathVariable("storeId") id: Long,
@RequestBody menuCreateCommand: MenuCreateCommand,
): ApiResponse<Long> {
return ApiResponse.success(menuCommandService.create(id, menuCreateCommand))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.mjucow.eatda.presentation.store.menu

import com.mjucow.eatda.domain.store.service.command.MenuCommandService
import com.mjucow.eatda.domain.store.service.command.dto.MenuUpdateCommand
import com.mjucow.eatda.domain.store.service.query.MenuDto
import com.mjucow.eatda.domain.store.service.query.MenuQueryService
import com.mjucow.eatda.presentation.common.ApiResponse
import org.springframework.http.HttpStatus
import org.springframework.web.bind.annotation.DeleteMapping
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PatchMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.ResponseStatus
import org.springframework.web.bind.annotation.RestController

@RestController
@RequestMapping("/api/v1/menu")
class MenuController(
private val queryService: MenuQueryService,
private val commandService: MenuCommandService,
) {
@GetMapping("/{menuId}")
@ResponseStatus(HttpStatus.OK)
fun findById(@PathVariable("menuId") id: Long): ApiResponse<MenuDto> {
return ApiResponse.success(queryService.findById(id))
}

@PatchMapping("/{menuId}")
@ResponseStatus(HttpStatus.OK)
fun updateById(@PathVariable("menuId") id: Long, @RequestBody command: MenuUpdateCommand) {
commandService.update(id, command)
}

@DeleteMapping("/{menuId}")
@ResponseStatus(HttpStatus.NO_CONTENT)
fun deleteById(@PathVariable("menuId") id: Long) {
commandService.delete(id)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,14 @@ class MenuCommandServiceTest : AbstractDataTest() {
@Test
fun test1() {
// given
val storeId = Long.MAX_VALUE
val command = MenuCreateCommand(
storeId = Long.MAX_VALUE,
name = MenuMother.NAME,
price = MenuMother.PRICE
)

// when
val throwable = catchThrowable { commandService.create(command) }
val throwable = catchThrowable { commandService.create(storeId, command) }

// then
assertThat(throwable).isNotNull()
Expand All @@ -56,13 +56,12 @@ class MenuCommandServiceTest : AbstractDataTest() {
// given
val store = storeRepository.save(StoreMother.create())
val command = MenuCreateCommand(
storeId = store.id,
name = MenuMother.NAME,
price = MenuMother.PRICE
)

// when
val menuId = commandService.create(command)
val menuId = commandService.create(store.id, command)

// then
assertThat(repository.getReferenceById(menuId)).isNotNull()
Expand All @@ -72,14 +71,14 @@ class MenuCommandServiceTest : AbstractDataTest() {
@Test
fun test3() {
// given
val id = Long.MAX_VALUE
val command = MenuUpdateCommand(
id = 1L,
name = MenuMother.NAME,
price = MenuMother.PRICE
)

// when
val throwable = catchThrowable { commandService.update(command) }
val throwable = catchThrowable { commandService.update(id, command) }

// then
assertThat(throwable).isNotNull()
Expand All @@ -93,13 +92,12 @@ class MenuCommandServiceTest : AbstractDataTest() {
val updatedName = "updateName"
val updatedPrice = MenuMother.PRICE * 2
val command = MenuUpdateCommand(
id = menu.id,
name = updatedName,
price = updatedPrice
)

// when
commandService.update(command)
commandService.update(menu.id, command)

// then
val updatedMenu = repository.getReferenceById(menu.id)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,17 @@ package com.mjucow.eatda.presentation.store
import com.epages.restdocs.apispec.MockMvcRestDocumentationWrapper
import com.epages.restdocs.apispec.ResourceDocumentation
import com.epages.restdocs.apispec.ResourceSnippetParametersBuilder
import com.mjucow.eatda.domain.store.entity.objectmother.MenuMother
import com.mjucow.eatda.domain.store.entity.objectmother.StoreMother
import com.mjucow.eatda.domain.store.service.command.MenuCommandService
import com.mjucow.eatda.domain.store.service.command.StoreCommandService
import com.mjucow.eatda.domain.store.service.command.dto.MenuCreateCommand
import com.mjucow.eatda.domain.store.service.command.dto.StoreCreateCommand
import com.mjucow.eatda.domain.store.service.command.dto.StoreUpdateCommand
import com.mjucow.eatda.domain.store.service.query.MenuDto
import com.mjucow.eatda.domain.store.service.query.MenuQueryService
import com.mjucow.eatda.domain.store.service.query.StoreQueryService
import com.mjucow.eatda.domain.store.service.query.dto.MenuList
import com.mjucow.eatda.domain.store.service.query.dto.StoreDetailDto
import com.mjucow.eatda.domain.store.service.query.dto.StoreDto
import com.mjucow.eatda.presentation.AbstractMockMvcTest
Expand All @@ -33,6 +39,12 @@ class StoreControllerMvcTest : AbstractMockMvcTest() {
@MockkBean(relaxUnitFun = true)
lateinit var storeCommandService: StoreCommandService

@MockkBean(relaxUnitFun = true)
lateinit var menuQueryService: MenuQueryService

@MockkBean(relaxUnitFun = true)
lateinit var menuCommandService: MenuCommandService

@Test
fun create() {
// given
Expand Down Expand Up @@ -232,6 +244,79 @@ class StoreControllerMvcTest : AbstractMockMvcTest() {
)
}

@Test
fun createMenu() {
// given
val entityId = 1L
every { menuCommandService.create(any(), any()) } returns entityId
val command = MenuCreateCommand(
name = MenuMother.NAME,
price = MenuMother.PRICE,
imageAddress = MenuMother.IMAGE_ADDRESS
)
val content = objectMapper.writeValueAsString(command)

// when & then
mockMvc.perform(
RestDocumentationRequestBuilders.post("$BASE_URI/{storeId}/menu", 1L)
.contentType(MediaType.APPLICATION_JSON)
.content(content)
)
.andExpect(MockMvcResultMatchers.status().isCreated)
.andExpect(MockMvcResultMatchers.jsonPath("message", `is`(IsNull.nullValue())))
.andExpect(MockMvcResultMatchers.jsonPath("body", `is`(entityId), Long::class.java))
.andDo(
MockMvcRestDocumentationWrapper.document(
identifier = "menu-create",
resourceDetails = ResourceSnippetParametersBuilder()
.tag("Store")
.description("가게의 메뉴 생성")
.pathParameters(
ResourceDocumentation.parameterWithName("storeId").description("가게 식별자")
)
.responseFields(
PayloadDocumentation.fieldWithPath("message").type(JsonFieldType.STRING).description("에러 메세지"),
PayloadDocumentation.fieldWithPath("body").type(JsonFieldType.NUMBER).description("가게 식별자")
)
)
)
}

@Test
fun findAllMenu() {
// given
val entityId = 1L
val dto = MenuDto.from(MenuMother.createWithId(id = entityId))
every { menuQueryService.findAll(any()) } returns MenuList(listOf(dto))

// when & then
mockMvc.perform(
RestDocumentationRequestBuilders.get("$BASE_URI/{storeId}/menu", 1L)
)
.andExpect(MockMvcResultMatchers.status().isOk)
.andExpect(MockMvcResultMatchers.jsonPath("message", `is`(IsNull.nullValue())))
.andExpect(MockMvcResultMatchers.jsonPath("body").exists())
.andDo(
MockMvcRestDocumentationWrapper.document(
identifier = "store-findAllMenu",
resourceDetails = ResourceSnippetParametersBuilder()
.tag("Store")
.description("가게의 메뉴 전체 조회")
.pathParameters(
ResourceDocumentation.parameterWithName("storeId").description("가게 식별자")
)
.responseFields(
PayloadDocumentation.fieldWithPath("message").type(JsonFieldType.STRING).description("에러 메세지"),
PayloadDocumentation.fieldWithPath("body").type(JsonFieldType.ARRAY).description("조회된 가게 메뉴 리스트"),
PayloadDocumentation.fieldWithPath("body[0].id").type(JsonFieldType.NUMBER).description("메뉴 식별자"),
PayloadDocumentation.fieldWithPath("body[0].name").type(JsonFieldType.STRING).description("메뉴 이름"),
PayloadDocumentation.fieldWithPath("body[0].price").type(JsonFieldType.NUMBER).description("메뉴 가격"),
PayloadDocumentation.fieldWithPath("body[0].imageAddress").type(JsonFieldType.STRING).description("메뉴 이미지 주소")
)
)
)
}

companion object {
const val BASE_URI = "/api/v1/stores"
}
Expand Down
Loading

0 comments on commit 2c852c7

Please sign in to comment.