From 8d12410addb024f9967126599c0beb5162027ea5 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" <once29@naver.com> Date: Mon, 22 Apr 2024 18:44:33 +0900 Subject: [PATCH 1/5] Remove unnecessary codes --- .../goalgifticon/GoalGifticonApplicationService.kt | 7 +++---- .../raisedragon/controller/goalgifticon/GoalGifticonDto.kt | 5 ----- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/raisedragon-api/src/main/kotlin/com/whatever/raisedragon/applicationservice/goalgifticon/GoalGifticonApplicationService.kt b/raisedragon-api/src/main/kotlin/com/whatever/raisedragon/applicationservice/goalgifticon/GoalGifticonApplicationService.kt index 9498eb9..597c7f7 100644 --- a/raisedragon-api/src/main/kotlin/com/whatever/raisedragon/applicationservice/goalgifticon/GoalGifticonApplicationService.kt +++ b/raisedragon-api/src/main/kotlin/com/whatever/raisedragon/applicationservice/goalgifticon/GoalGifticonApplicationService.kt @@ -8,10 +8,10 @@ import com.whatever.raisedragon.common.exception.BaseException import com.whatever.raisedragon.common.exception.ExceptionCode import com.whatever.raisedragon.domain.gifticon.GifticonService import com.whatever.raisedragon.domain.gifticon.URL -import com.whatever.raisedragon.domain.goal.* +import com.whatever.raisedragon.domain.goal.Goal +import com.whatever.raisedragon.domain.goal.GoalService +import com.whatever.raisedragon.domain.goal.GoalType import com.whatever.raisedragon.domain.goalgifticon.GoalGifticonService -import com.whatever.raisedragon.domain.user.UserService -import com.whatever.raisedragon.domain.user.fromDto import com.whatever.raisedragon.domain.winner.WinnerService import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @@ -23,7 +23,6 @@ class GoalGifticonApplicationService( private val gifticonService: GifticonService, private val goalService: GoalService, private val goalGifticonService: GoalGifticonService, - private val userService: UserService, private val winnerService: WinnerService ) { diff --git a/raisedragon-api/src/main/kotlin/com/whatever/raisedragon/controller/goalgifticon/GoalGifticonDto.kt b/raisedragon-api/src/main/kotlin/com/whatever/raisedragon/controller/goalgifticon/GoalGifticonDto.kt index 6a7e706..eca14cc 100644 --- a/raisedragon-api/src/main/kotlin/com/whatever/raisedragon/controller/goalgifticon/GoalGifticonDto.kt +++ b/raisedragon-api/src/main/kotlin/com/whatever/raisedragon/controller/goalgifticon/GoalGifticonDto.kt @@ -3,16 +3,13 @@ package com.whatever.raisedragon.controller.goalgifticon import com.whatever.raisedragon.applicationservice.goalgifticon.dto.GoalGifticonCreateServiceRequest import com.whatever.raisedragon.applicationservice.goalgifticon.dto.GoalGifticonUpdateServiceRequest import io.swagger.v3.oas.annotations.media.Schema -import jakarta.validation.constraints.NotNull @Schema(description = "[Request] 다짐에 기프티콘 업로드") data class GoalGifticonCreateRequest( @Schema(description = "기프티콘을 등록할 다짐의 Id") - @field:NotNull val goalId: Long, @Schema(description = "기프티콘 URL") - @field:NotNull val gifticonURL: String ) @@ -27,11 +24,9 @@ fun GoalGifticonCreateRequest.toServiceRequest( @Schema(description = "[Request] 다짐 기프티콘 수정") data class GoalGifticonRequest( @Schema(description = "기프티콘을 등록할 다짐의 Id") - @field:NotNull val goalId: Long, @Schema(description = "기프티콘 URL") - @field:NotNull val gifticonURL: String ) From eeb32d5e9b261eaceb9250634bbd4ad6bf10730c Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" <once29@naver.com> Date: Mon, 22 Apr 2024 18:45:10 +0900 Subject: [PATCH 2/5] Add extension functions for testing well in ControllerTestSupport --- .../raisedragon/ControllerTestSupport.kt | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/raisedragon-api/src/test/kotlin/com/whatever/raisedragon/ControllerTestSupport.kt b/raisedragon-api/src/test/kotlin/com/whatever/raisedragon/ControllerTestSupport.kt index 01a3052..c2f967b 100644 --- a/raisedragon-api/src/test/kotlin/com/whatever/raisedragon/ControllerTestSupport.kt +++ b/raisedragon-api/src/test/kotlin/com/whatever/raisedragon/ControllerTestSupport.kt @@ -2,17 +2,23 @@ package com.whatever.raisedragon import com.fasterxml.jackson.databind.ObjectMapper import com.whatever.raisedragon.applicationservice.betting.BettingApplicationService +import com.whatever.raisedragon.applicationservice.goalgifticon.GoalGifticonApplicationService import com.whatever.raisedragon.controller.betting.BettingController +import com.whatever.raisedragon.controller.goalgifticon.GoalGifticonController import org.mockito.Mockito.* import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest import org.springframework.boot.test.mock.mockito.MockBean +import org.springframework.http.MediaType +import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors import org.springframework.test.context.ActiveProfiles import org.springframework.test.web.servlet.MockMvc +import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder @WebMvcTest( controllers = [ - BettingController::class + BettingController::class, + GoalGifticonController::class, ] ) @ActiveProfiles("test") @@ -26,4 +32,19 @@ abstract class ControllerTestSupport { @MockBean protected lateinit var bettingApplicationService: BettingApplicationService + + @MockBean + protected lateinit var goalGifticonApplicationService: GoalGifticonApplicationService + + protected fun MockHttpServletRequestBuilder.withCsrf(): MockHttpServletRequestBuilder { + return with(SecurityMockMvcRequestPostProcessors.csrf()) + } + + protected fun MockHttpServletRequestBuilder.writeRequestAsContent(request: Any): MockHttpServletRequestBuilder { + return content(objectMapper.writeValueAsString(request)) + } + + protected fun MockHttpServletRequestBuilder.contentTypeAsJson(): MockHttpServletRequestBuilder { + return contentType(MediaType.APPLICATION_JSON) + } } \ No newline at end of file From 7befabb947cd90da9f78d717b3bbf0825d0a3b98 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" <once29@naver.com> Date: Mon, 22 Apr 2024 18:45:57 +0900 Subject: [PATCH 3/5] Fix type of request at GoalGifticonController.create --- .../controller/goalgifticon/GoalGifticonController.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/raisedragon-api/src/main/kotlin/com/whatever/raisedragon/controller/goalgifticon/GoalGifticonController.kt b/raisedragon-api/src/main/kotlin/com/whatever/raisedragon/controller/goalgifticon/GoalGifticonController.kt index 14ea1a2..d2b53bd 100644 --- a/raisedragon-api/src/main/kotlin/com/whatever/raisedragon/controller/goalgifticon/GoalGifticonController.kt +++ b/raisedragon-api/src/main/kotlin/com/whatever/raisedragon/controller/goalgifticon/GoalGifticonController.kt @@ -29,7 +29,7 @@ class GoalGifticonController( @PostMapping fun create( @GetAuth userInfo: UserInfo, - @Valid request: GoalGifticonCreateRequest, + @Valid @RequestBody request: GoalGifticonCreateRequest, ): Response<GoalGifticonResponse> { return Response.success( goalGifticonApplicationService.createAndUploadGifticon(request.toServiceRequest(userInfo.id)) From 5ccb645eb9b6a85903520c6bba24f8545b272149 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" <once29@naver.com> Date: Mon, 22 Apr 2024 18:46:14 +0900 Subject: [PATCH 4/5] Fix wrong types of response status in GoalGifticon api --- .../controller/goalgifticon/GoalGifticonController.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/raisedragon-api/src/main/kotlin/com/whatever/raisedragon/controller/goalgifticon/GoalGifticonController.kt b/raisedragon-api/src/main/kotlin/com/whatever/raisedragon/controller/goalgifticon/GoalGifticonController.kt index d2b53bd..f6ab133 100644 --- a/raisedragon-api/src/main/kotlin/com/whatever/raisedragon/controller/goalgifticon/GoalGifticonController.kt +++ b/raisedragon-api/src/main/kotlin/com/whatever/raisedragon/controller/goalgifticon/GoalGifticonController.kt @@ -36,7 +36,6 @@ class GoalGifticonController( ) } - @ResponseStatus(HttpStatus.CREATED) @Operation( summary = "다짐 내 기프티콘 조회 API", description = "다짐 내 기프티콘 조회 (나의 기프티콘 이거나 승리한 경우 조회 가능)", @@ -52,7 +51,6 @@ class GoalGifticonController( ) } - @ResponseStatus(HttpStatus.CREATED) @Operation( summary = "다짐 내 기프티콘 수정 API", description = "다짐 내 기프티콘 수정", From 4ba9d9eb0ee650ed7f2e4067be9b237ffd070707 Mon Sep 17 00:00:00 2001 From: "Jaemin.Park" <once29@naver.com> Date: Mon, 22 Apr 2024 18:46:29 +0900 Subject: [PATCH 5/5] Write test codes of GoalGifticonController --- .../betting/BettingControllerTest.kt | 20 +++-- .../GoalGifticonControllerTest.kt | 74 +++++++++++++++++++ 2 files changed, 83 insertions(+), 11 deletions(-) create mode 100644 raisedragon-api/src/test/kotlin/com/whatever/raisedragon/controller/goalgifticon/GoalGifticonControllerTest.kt diff --git a/raisedragon-api/src/test/kotlin/com/whatever/raisedragon/controller/betting/BettingControllerTest.kt b/raisedragon-api/src/test/kotlin/com/whatever/raisedragon/controller/betting/BettingControllerTest.kt index 8fc40d7..11c2de6 100644 --- a/raisedragon-api/src/test/kotlin/com/whatever/raisedragon/controller/betting/BettingControllerTest.kt +++ b/raisedragon-api/src/test/kotlin/com/whatever/raisedragon/controller/betting/BettingControllerTest.kt @@ -9,8 +9,6 @@ import org.hamcrest.core.IsNull.nullValue import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.Test import org.mockito.Mockito.* -import org.springframework.http.MediaType -import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.* import org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status @@ -28,9 +26,9 @@ class BettingControllerTest : ControllerTestSupport() { mockMvc .perform( post("/v1/betting") - .with(csrf()) - .content(objectMapper.writeValueAsString(request)) - .contentType(MediaType.APPLICATION_JSON) + .withCsrf() + .writeRequestAsContent(request) + .contentTypeAsJson() ) .andDo(::print) .andExpect(status().isCreated()) @@ -48,9 +46,9 @@ class BettingControllerTest : ControllerTestSupport() { mockMvc .perform( post("/v1/betting") - .with(csrf()) - .content(objectMapper.writeValueAsString(request)) - .contentType(MediaType.APPLICATION_JSON) + .withCsrf() + .writeRequestAsContent(request) + .contentTypeAsJson() ) .andDo(::print) .andExpect(status().isBadRequest) @@ -87,9 +85,9 @@ class BettingControllerTest : ControllerTestSupport() { mockMvc .perform( put("/v1/betting") - .with(csrf()) - .content(objectMapper.writeValueAsString(request)) - .contentType(MediaType.APPLICATION_JSON) + .withCsrf() + .writeRequestAsContent(request) + .contentTypeAsJson() ) .andDo(::print) .andExpect(status().isOk) diff --git a/raisedragon-api/src/test/kotlin/com/whatever/raisedragon/controller/goalgifticon/GoalGifticonControllerTest.kt b/raisedragon-api/src/test/kotlin/com/whatever/raisedragon/controller/goalgifticon/GoalGifticonControllerTest.kt new file mode 100644 index 0000000..2fa513c --- /dev/null +++ b/raisedragon-api/src/test/kotlin/com/whatever/raisedragon/controller/goalgifticon/GoalGifticonControllerTest.kt @@ -0,0 +1,74 @@ +package com.whatever.raisedragon.controller.goalgifticon + +import com.whatever.raisedragon.ControllerTestSupport +import com.whatever.raisedragon.security.WithCustomUser +import org.hamcrest.core.IsNull.nullValue +import org.junit.jupiter.api.Assertions.* +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Test +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get +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 + +@WithCustomUser(id = 1L, nickname = "User") +class GoalGifticonControllerTest : ControllerTestSupport() { + + @DisplayName("GoalGifticon을 생성한다.") + @Test + fun create() { + // given + val gifticonUrl = "www.sample.com/gifticon" + val request = GoalGifticonCreateRequest(goalId = 1L, gifticonURL = gifticonUrl) + + // when // then + mockMvc + .perform( + post("/v1/goal-gifticon") + .withCsrf() + .writeRequestAsContent(request) + .contentTypeAsJson() + ) + .andDo(::print) + .andExpect(status().isCreated) + .andExpect(jsonPath("$.isSuccess").value(true)) + .andExpect(jsonPath("$.errorResponse").value(nullValue())) + } + + @DisplayName("다짐 내 GoalGifticon을 조회한다.") + @Test + fun retrieve() { + // given + val goalId = 1L + + // when // then + mockMvc + .perform( + get("/v1/goal-gifticon/$goalId") + ) + .andDo(::print) + .andExpect(status().isOk) + .andExpect(jsonPath("$.isSuccess").value(true)) + .andExpect(jsonPath("$.errorResponse").value(nullValue())) + } + + @DisplayName("다짐 내 기프티콘을 수정한다.") + @Test + fun update() { + // given + val gifticonUrl = "www.sample.com/updated-gifticon" + val request = GoalGifticonRequest(goalId = 1L, gifticonURL = gifticonUrl) + + // when // then + mockMvc + .perform( + post("/v1/goal-gifticon") + .withCsrf() + .writeRequestAsContent(request) + .contentTypeAsJson() + ) + .andDo(::print) + .andExpect(jsonPath("$.isSuccess").value(true)) + .andExpect(jsonPath("$.errorResponse").value(nullValue())) + } +} \ No newline at end of file