[#20] 도메인별 예외 분리 #21

Merged
pricelees merged 37 commits from refactor/#20 into main 2025-07-24 02:48:53 +00:00
2 changed files with 35 additions and 41 deletions
Showing only changes of commit 16426c9f99 - Show all commits

View File

@ -2,7 +2,6 @@ package roomescape.common.exception
import io.github.oshai.kotlinlogging.KLogger
import io.github.oshai.kotlinlogging.KotlinLogging
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.http.converter.HttpMessageNotReadableException
import org.springframework.web.bind.MethodArgumentNotValidException
@ -20,8 +19,8 @@ class ExceptionControllerAdvice(
logger.error(e) { "message: ${e.message}" }
val errorCode: ErrorCode = e.errorCode
val httpStatus: Int = errorCode.httpStatus.value()
return ResponseEntity.status(httpStatus)
return ResponseEntity
.status(errorCode.httpStatus)
.body(CommonErrorResponseV2(errorCode, e.message))
}
@ -35,32 +34,35 @@ class ExceptionControllerAdvice(
}
@ExceptionHandler(value = [HttpMessageNotReadableException::class])
fun handleHttpMessageNotReadableException(e: HttpMessageNotReadableException): ResponseEntity<CommonErrorResponse> {
fun handleHttpMessageNotReadableException(e: HttpMessageNotReadableException): ResponseEntity<CommonErrorResponseV2> {
logger.error(e) { "message: ${e.message}" }
val errorCode: ErrorCode = CommonErrorCode.INVALID_INPUT_VALUE
return ResponseEntity
.status(HttpStatus.BAD_REQUEST)
.body(CommonErrorResponse(ErrorType.INVALID_REQUEST_DATA_TYPE))
.status(errorCode.httpStatus)
.body(CommonErrorResponseV2(errorCode, e.message ?: errorCode.message))
}
@ExceptionHandler(value = [MethodArgumentNotValidException::class])
fun handleMethodArgumentNotValidException(e: MethodArgumentNotValidException): ResponseEntity<CommonErrorResponse> {
val messages: String = e.bindingResult.allErrors
fun handleMethodArgumentNotValidException(e: MethodArgumentNotValidException): ResponseEntity<CommonErrorResponseV2> {
val message: String = e.bindingResult.allErrors
.mapNotNull { it.defaultMessage }
.joinToString(", ")
logger.error(e) { "message: $messages" }
logger.error(e) { "message: $message" }
val errorCode: ErrorCode = CommonErrorCode.INVALID_INPUT_VALUE
return ResponseEntity
.status(HttpStatus.BAD_REQUEST)
.body(CommonErrorResponse(ErrorType.INVALID_REQUEST_DATA, messages))
.status(errorCode.httpStatus)
.body(CommonErrorResponseV2(errorCode, message))
}
@ExceptionHandler(value = [Exception::class])
fun handleException(e: Exception): ResponseEntity<CommonErrorResponse> {
fun handleException(e: Exception): ResponseEntity<CommonErrorResponseV2> {
logger.error(e) { "message: ${e.message}" }
val errorCode: ErrorCode = CommonErrorCode.UNEXPECTED_SERVER_ERROR
return ResponseEntity
.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(CommonErrorResponse(ErrorType.UNEXPECTED_ERROR))
.status(errorCode.httpStatus)
.body(CommonErrorResponseV2(errorCode))
}
}

View File

@ -4,18 +4,19 @@ import com.ninjasquad.springmockk.SpykBean
import io.mockk.every
import org.hamcrest.Matchers.containsString
import org.hamcrest.Matchers.equalTo
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest
import org.springframework.data.repository.findByIdOrNull
import org.springframework.test.web.servlet.MockMvc
import roomescape.auth.service.AuthService
import roomescape.common.exception.CommonErrorCode
import roomescape.common.exception.ErrorCode
import roomescape.common.exception.ErrorType
import roomescape.util.MemberFixture
import roomescape.util.RoomescapeApiTest
@WebMvcTest(controllers = [AuthController::class])
class AuthControllerTest(
@Autowired mockMvc: MockMvc
val mockMvc: MockMvc
) : RoomescapeApiTest() {
@SpykBean
@ -71,32 +72,23 @@ class AuthControllerTest(
}
}
}
When("입력 값이 잘못되면") {
val expectedErrorCode: ErrorCode = CommonErrorCode.INVALID_INPUT_VALUE
When("잘못된 요청을 보내면 400 에러를 응답한다.") {
Then("이메일 형식이 잘못된 경우") {
val invalidRequest: LoginRequest = userRequest.copy(email = "invalid")
runPostTest(
mockMvc = mockMvc,
endpoint = endpoint,
body = invalidRequest,
) {
status { isBadRequest() }
jsonPath("$.message", containsString("이메일 형식이 일치하지 않습니다."))
}
}
Then("비밀번호가 공백인 경우") {
val invalidRequest = userRequest.copy(password = " ")
runPostTest(
mockMvc = mockMvc,
endpoint = endpoint,
body = invalidRequest,
) {
status { isBadRequest() }
jsonPath("$.message", containsString("비밀번호는 공백일 수 없습니다."))
Then("400 에러를 응답한다") {
listOf(
userRequest.copy(email = "invalid"),
userRequest.copy(password = " "),
"{\"email\": \"null\", \"password\": \"null\"}"
).forEach {
runPostTest(
mockMvc = mockMvc,
endpoint = endpoint,
body = it,
) {
status { isEqualTo(expectedErrorCode.httpStatus.value()) }
jsonPath("$.code", equalTo(expectedErrorCode.errorCode))
}
}
}
}