Skip to content

Commit

Permalink
Merge pull request #95 from whatever-mentoring/feature/goal-proof-con…
Browse files Browse the repository at this point in the history
…troller-test

Write test codes of GoalProofController
  • Loading branch information
mkSpace authored May 21, 2024
2 parents dcf5689 + 3e2f9c4 commit 840a44e
Show file tree
Hide file tree
Showing 5 changed files with 226 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class GoalProofController(
}

@Operation(summary = "Retrieving GoalProofs API", description = "모든 다짐 인증을 조회합니다")
@GetMapping("goal/{goalId}/goal-proof")
@GetMapping("/goal/{goalId}/goal-proof")
fun retrieveAll(
@GetAuth userInfo: UserInfo,
@PathVariable goalId: Long
Expand All @@ -51,7 +51,7 @@ class GoalProofController(
}

@Operation(summary = "Retrieving GoalProofs' result API", description = "해당 다짐이 성공했는지 여부를 알려줍니다")
@GetMapping("goal/{goalId}/goal-proof/result")
@GetMapping("/goal/{goalId}/goal-proof/result")
fun isGoalSuccess(
@GetAuth userInfo: UserInfo,
@PathVariable goalId: Long
Expand All @@ -63,7 +63,7 @@ class GoalProofController(
@PutMapping("/goal-proof/{goalProofId}")
fun update(
@PathVariable goalProofId: Long,
@RequestBody request: GoalProofUpdateRequest,
@Valid @RequestBody request: GoalProofUpdateRequest,
@GetAuth userInfo: UserInfo
): Response<GoalProofRetrieveResponse> {
return Response.success(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,19 @@ import com.whatever.raisedragon.applicationservice.goalproof.dto.GoalProofUpdate
import com.whatever.raisedragon.domain.gifticon.URL
import com.whatever.raisedragon.domain.goalproof.Comment
import io.swagger.v3.oas.annotations.media.Schema
import jakarta.validation.constraints.NotBlank

@Schema(description = "[Request] 다짐 인증 생성")
data class GoalProofCreateRequest(
@Schema(description = "Goal Id")
val goalId: Long,

@Schema(description = "다짐 인증에 사용한 이미지 url")
@field:NotBlank(message = "URL은 공백이어서는 안됩니다.")
val url: String,

@Schema(description = "다짐 인증에 대한 부연설명")
@field:NotBlank(message = "Comment는 공백이어서는 안됩니다.")
val comment: String
)

Expand All @@ -30,9 +33,11 @@ fun GoalProofCreateRequest.toServiceRequest(
@Schema(description = "[Request] 다짐 인증 수정")
data class GoalProofUpdateRequest(
@Schema(description = "다짐 인증에 사용한 이미지 url")
@field:NotBlank(message = "URL은 공백이어서는 안됩니다.")
val url: String? = null,

@Schema(description = "다짐 인증에 대한 부연설명")
@field:NotBlank(message = "Comment는 공백이어서는 안됩니다.")
val comment: String? = null
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ 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.applicationservice.goalproof.GoalProofApplicationService
import com.whatever.raisedragon.controller.betting.BettingController
import com.whatever.raisedragon.controller.goalgifticon.GoalGifticonController
import org.mockito.Mockito.*
import com.whatever.raisedragon.controller.goalproof.GoalProofController
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest
import org.springframework.boot.test.mock.mockito.MockBean
Expand All @@ -19,6 +20,7 @@ import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilde
controllers = [
BettingController::class,
GoalGifticonController::class,
GoalProofController::class
]
)
@ActiveProfiles("test")
Expand All @@ -36,6 +38,9 @@ abstract class ControllerTestSupport {
@MockBean
protected lateinit var goalGifticonApplicationService: GoalGifticonApplicationService

@MockBean
protected lateinit var goalProofApplicationService: GoalProofApplicationService

protected fun MockHttpServletRequestBuilder.withCsrf(): MockHttpServletRequestBuilder {
return with(SecurityMockMvcRequestPostProcessors.csrf())
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
package com.whatever.raisedragon.controller.goalproof

import com.whatever.raisedragon.ControllerTestSupport
import com.whatever.raisedragon.applicationservice.goalproof.dto.GoalProofListRetrieveResponse
import com.whatever.raisedragon.applicationservice.goalproof.dto.GoalProofRetrieveResponse
import com.whatever.raisedragon.security.WithCustomUser
import org.hamcrest.core.IsNull.nullValue
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import org.mockito.Mockito.`when`
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

@WithCustomUser(id = 1L, nickname = "User")
class GoalProofControllerTest : ControllerTestSupport() {

@DisplayName("GoalProof를 생성한다.")
@Test
fun create() {
// given
val request = GoalProofCreateRequest(goalId = 1L, url = "www.sample.com", comment = "Sample Comment")

// when // then
mockMvc
.perform(
post("/v1/goal-proof")
.withCsrf()
.writeRequestAsContent(request)
.contentTypeAsJson()
)
.andDo(::print)
.andExpect(status().isCreated)
.andExpect(jsonPath("$.isSuccess").value(true))
.andExpect(jsonPath("$.errorResponse").value(nullValue()))
}

@DisplayName("GoalProof를 생성할 때 URL은 공백이 아니다.")
@Test
fun createWithBlankUrl() {
// given
val request = GoalProofCreateRequest(goalId = 1L, url = "", comment = "Sample Comment")

// when // then
mockMvc
.perform(
post("/v1/goal-proof")
.withCsrf()
.writeRequestAsContent(request)
.contentTypeAsJson()
)
.andDo(::print)
.andExpect(status().isBadRequest)
.andExpect(jsonPath("$.errorResponse.code").value("400"))
.andExpect(jsonPath("$.errorResponse.detailMessage").value("URL은 공백이어서는 안됩니다."))
.andExpect(jsonPath("$.data").isEmpty())
}

@DisplayName("GoalProof를 생성할 때 Comment는 공백이 아니다.")
@Test
fun createWithBlankComment() {
// given
val request = GoalProofCreateRequest(goalId = 1L, url = "www.sample.com", comment = "")

// when // then
mockMvc
.perform(
post("/v1/goal-proof")
.withCsrf()
.writeRequestAsContent(request)
.contentTypeAsJson()
)
.andDo(::print)
.andExpect(status().isBadRequest)
.andExpect(jsonPath("$.errorResponse.code").value("400"))
.andExpect(jsonPath("$.errorResponse.detailMessage").value("Comment는 공백이어서는 안됩니다."))
.andExpect(jsonPath("$.data").isEmpty())
}

@DisplayName("GoalProof를 조회한다.")
@Test
fun retrieve() {
// given
val goalProofId = 1L

// when // then
mockMvc
.perform(
get("/v1/goal-proof/$goalProofId")
)
.andDo(::print)
.andExpect(status().isOk)
.andExpect(jsonPath("$.isSuccess").value(true))
.andExpect(jsonPath("$.errorResponse").value(nullValue()))
}

@DisplayName("모든 GoalProof를 조회한다.")
@Test
fun retrieveAll() {
// given
val goalId = 1L
val mockUserId = 1L
val goalProofs = listOf<GoalProofRetrieveResponse>()
val progressDays = listOf<Int>()

`when`(goalProofApplicationService.retrieveAll(goalId, mockUserId)).thenReturn(
GoalProofListRetrieveResponse(goalProofs, progressDays)
)
// when // then
mockMvc
.perform(
get("/v1/goal/$goalId/goal-proof")
)
.andDo(::print)
.andExpect(status().isOk)
.andExpect(jsonPath("$.isSuccess").value(true))
.andExpect(jsonPath("$.errorResponse").value(nullValue()))
.andExpect(jsonPath("$.data.goalProofs").isArray)
.andExpect(jsonPath("$.data.progressDays").isArray)
}

@DisplayName("해당 다짐이 성공했는지 여부를 조회한다.")
@Test
fun isGoalSuccess() {
// given
val goalId = 1L

// when // then
mockMvc
.perform(
get("/v1/goal/$goalId/goal-proof/result")
)
.andDo(::print)
.andExpect(status().isOk)
.andExpect(jsonPath("$.isSuccess").value(true))
.andExpect(jsonPath("$.errorResponse").value(nullValue()))
.andExpect(jsonPath("$.data").isBoolean)
}

@DisplayName("GoalProof를 수정한다.")
@Test
fun update() {
// given
val request = GoalProofUpdateRequest("www.sample.com", "Sample Comment")
val goalProofId = 1L

// when // then
mockMvc
.perform(
put("/v1/goal-proof/$goalProofId")
.withCsrf()
.writeRequestAsContent(request)
.contentTypeAsJson()
)
.andDo(::print)
.andExpect(status().isOk)
.andExpect(jsonPath("$.errorResponse").value(nullValue()))
}

@DisplayName("GoalProof를 수정할 때 URL은 공백이 아니다.")
@Test
fun updateWithBlankUrl() {
// given
val request = GoalProofUpdateRequest(url = "", comment = "Sample Comment")
val goalProofId = 1L

// when // then
mockMvc
.perform(
put("/v1/goal-proof/$goalProofId")

.withCsrf()
.writeRequestAsContent(request)
.contentTypeAsJson()
)
.andDo(::print)
.andExpect(status().isBadRequest)
.andExpect(jsonPath("$.errorResponse.code").value("400"))
.andExpect(jsonPath("$.errorResponse.detailMessage").value("URL은 공백이어서는 안됩니다."))
.andExpect(jsonPath("$.data").isEmpty())
}

@DisplayName("GoalProof를 수정할 때 Comment는 공백이 아니다.")
@Test
fun updateWithBlankComment() {
// given
val request = GoalProofUpdateRequest(url = "www.sample.com", comment = "")
val goalProofId = 1L

// when // then
mockMvc
.perform(
put("/v1/goal-proof/$goalProofId")
.withCsrf()
.writeRequestAsContent(request)
.contentTypeAsJson()
)
.andDo(::print)
.andExpect(status().isBadRequest)
.andExpect(jsonPath("$.errorResponse.code").value("400"))
.andExpect(jsonPath("$.errorResponse.detailMessage").value("Comment는 공백이어서는 안됩니다."))
.andExpect(jsonPath("$.data").isEmpty())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,28 @@ enum class ExceptionCode(
val message: String,
) {

E400_BAD_REQUEST(HttpStatus.BAD_REQUEST, "000", "필수 파라미터 값이 없거나 잘못된 값으로 요청을 보낸 경우 발생"),
E400_BAD_REQUEST(HttpStatus.BAD_REQUEST, "400", "필수 파라미터 값이 없거나 잘못된 값으로 요청을 보낸 경우 발생"),

// ------------------------------ 401 ------------------------------
E401_UNAUTHORIZED(HttpStatus.UNAUTHORIZED, "000", "유효하지 않은 인증 토큰을 사용한 경우 발생"),
E401_UNAUTHORIZED(HttpStatus.UNAUTHORIZED, "401", "유효하지 않은 인증 토큰을 사용한 경우 발생"),

// ------------------------------ 403 ------------------------------
E403_FORBIDDEN(HttpStatus.FORBIDDEN, "000", "사용 권한이 없는 경우 발생"),
E403_FORBIDDEN(HttpStatus.FORBIDDEN, "403", "사용 권한이 없는 경우 발생"),

// ------------------------------ 404 ------------------------------
E404_NOT_FOUND(HttpStatus.NOT_FOUND, "000", "요청한 리소스가 존재하지 않는 경우 발생"),
E404_NOT_FOUND(HttpStatus.NOT_FOUND, "404", "요청한 리소스가 존재하지 않는 경우 발생"),

// ------------------------------ 405 ------------------------------
E405_METHOD_NOT_ALLOWED(HttpStatus.METHOD_NOT_ALLOWED, "000", "HTTP Method가 잘못된 경우"),
E405_METHOD_NOT_ALLOWED(HttpStatus.METHOD_NOT_ALLOWED, "405", "HTTP Method가 잘못된 경우"),

// ------------------------------ 409 ------------------------------
E409_CONFLICT(HttpStatus.CONFLICT, "000", "요청한 리소스가 중복된 경우 발생"),
E409_CONFLICT(HttpStatus.CONFLICT, "409", "요청한 리소스가 중복된 경우 발생"),

// ------------------------------ 500 ------------------------------
E500_INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "000", "서버 내부에 문제 발생"),
E500_INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "500", "서버 내부에 문제 발생"),

// ------------------------------ 501 ------------------------------
E501_NOT_IMPLEMENTED(HttpStatus.NOT_IMPLEMENTED, "000", "지원하지 않는 타입의 요청"),
E501_NOT_IMPLEMENTED(HttpStatus.NOT_IMPLEMENTED, "501", "지원하지 않는 타입의 요청"),
}

fun ExceptionCode.throwAsException() {
Expand Down

0 comments on commit 840a44e

Please sign in to comment.