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