diff --git a/backend/src/main/java/com/zzang/chongdae/global/exception/GlobalExceptionHandler.java b/backend/src/main/java/com/zzang/chongdae/global/exception/GlobalExceptionHandler.java index c294e0155..ba748fef0 100644 --- a/backend/src/main/java/com/zzang/chongdae/global/exception/GlobalExceptionHandler.java +++ b/backend/src/main/java/com/zzang/chongdae/global/exception/GlobalExceptionHandler.java @@ -4,9 +4,12 @@ import com.zzang.chongdae.logging.dto.LoggingErrorResponse; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.ConstraintViolation; +import jakarta.validation.ConstraintViolationException; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; +import java.util.List; import java.util.UUID; import lombok.extern.slf4j.Slf4j; import org.springframework.http.ResponseEntity; @@ -39,6 +42,18 @@ public ResponseEntity handle(MethodArgumentNotValidException e) { .body(errorMessage); } + @ExceptionHandler + public ResponseEntity handle(ConstraintViolationException e) { + List messages = e.getConstraintViolations().stream() + .map(ConstraintViolation::getMessage) + .toList(); + ErrorMessage errorMessage = new ErrorMessage( + "요청값이 유효하지 않습니다: [%s]".formatted(messages.get(0))); + return ResponseEntity + .badRequest() + .body(errorMessage); + } + @ExceptionHandler public ResponseEntity handle(HandlerMethodValidationException e) { ErrorMessage errorMessage = new ErrorMessage( diff --git a/backend/src/main/java/com/zzang/chongdae/offering/repository/entity/OfferingEntity.java b/backend/src/main/java/com/zzang/chongdae/offering/repository/entity/OfferingEntity.java index 8be35d218..03f655c4e 100644 --- a/backend/src/main/java/com/zzang/chongdae/offering/repository/entity/OfferingEntity.java +++ b/backend/src/main/java/com/zzang/chongdae/offering/repository/entity/OfferingEntity.java @@ -16,6 +16,7 @@ import jakarta.persistence.Id; import jakarta.persistence.ManyToOne; import jakarta.persistence.Table; +import jakarta.validation.constraints.Max; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Positive; import java.time.LocalDateTime; @@ -34,6 +35,7 @@ public class OfferingEntity extends BaseTimeEntity { private static final int INITIAL_COUNT = 1; + private static final int MAX_TOTAL_COUNT = 999; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @@ -68,6 +70,7 @@ public class OfferingEntity extends BaseTimeEntity { @NotNull @Positive + @Max(value = MAX_TOTAL_COUNT, message = "최대로 설정 가능한 공모 모집 인원수를 초과하였습니다.") private Integer totalCount; @NotNull diff --git a/backend/src/test/java/com/zzang/chongdae/offering/integration/OfferingIntegrationTest.java b/backend/src/test/java/com/zzang/chongdae/offering/integration/OfferingIntegrationTest.java index 3465d958a..7e7094bd1 100644 --- a/backend/src/test/java/com/zzang/chongdae/offering/integration/OfferingIntegrationTest.java +++ b/backend/src/test/java/com/zzang/chongdae/offering/integration/OfferingIntegrationTest.java @@ -511,7 +511,34 @@ void should_throwException_when_dividedPrice() { ); given(spec).log().all() - .filter(document("create-offering-success", resource(failSnippets))) + .filter(document("create-offering-fail-with-invalid-originPrice", resource(failSnippets))) + .cookies(cookieProvider.createCookies()) + .contentType(ContentType.JSON) + .body(request) + .when().post("/offerings") + .then().log().all() + .statusCode(400); + } + + @DisplayName("최대로 설정 가능한 공모 모집 인원수를 초과하는 경우 예외가 발생한다.") + @Test + void should_throwException_when_overMaximumTotalCount() { + OfferingSaveRequest request = new OfferingSaveRequest( + "공모 제목", + "www.naver.com", + "www.naver.com/favicon.ico", + 999999999, + 10000, + 2000, + "서울특별시 광진구 구의강변로 3길 11", + "상세주소아파트", + "구의동", + LocalDateTime.parse("2024-10-11T10:00:00"), + "내용입니다." + ); + + given(spec).log().all() + .filter(document("create-offering-fail-with-invalid-totalCount", resource(failSnippets))) .cookies(cookieProvider.createCookies()) .contentType(ContentType.JSON) .body(request)