Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feature] menu api 구현 및 테스트 작성 #31

Merged
merged 1 commit into from
Oct 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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