-
Notifications
You must be signed in to change notification settings - Fork 0
Maintenance: ControllerAdvice - Add validation exception handlers and tests #114
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Maintenance: ControllerAdvice - Add validation exception handlers and tests #114
Conversation
… tests ## Issues Found **Missing Validation Exception Handlers** - The ControllerAdvice was missing handlers for Spring validation exceptions - When @Valid annotation is used on request objects (e.g., NotificationCreateTokenRequest), validation failures would return Spring's default error response instead of the application's standard ApiResponse format - No handler for malformed JSON requests (HttpMessageNotReadableException) **No Tests** - The ControllerAdvice class had no tests to verify exception handling behavior - This meant validation and error handling could break without detection ## Changes Made **Added Exception Handlers:** 1. MethodArgumentNotValidException handler - handles @Valid annotation failures - Returns field-level validation errors in a Map - Uses BAD_REQUEST (400) status with ErrorType.EXTERNAL_SERVICE_BAD_REQUEST - Provides clear field-to-error mapping for client consumption 2. HttpMessageNotReadableException handler - handles malformed JSON - Returns user-friendly Korean error message - Uses BAD_REQUEST (400) status **Added Comprehensive Tests:** - Created ControllerAdviceTest with 4 test cases: 1. Validation failure with field errors 2. Malformed JSON request handling 3. Custom MemeWikiApplicationException handling 4. Unexpected exception handling - Uses standalone MockMvc setup for clean, focused testing - All tests verify both HTTP status codes and response structure ## Why This Improves the Code **Consistency:** All API errors now use the standard ApiResponse format **User Experience:** Validation errors provide clear, actionable field-level feedback **Maintainability:** Tests ensure exception handling won't regress **API Design:** Proper HTTP status codes and error messages for different scenarios 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Code Review - PR #114: ControllerAdvice Validation Exception HandlersOverall Assessment✅ APPROVED - This is a solid maintenance PR that addresses a real gap in exception handling. The changes are well-implemented with good test coverage. 🟢 Strengths1. Addresses Real Issues
2. Test Coverage
3. Consistent Error Format
4. Good Logging Practices
🟡 Issues & RecommendationsISSUE 1: Semantic Misuse of ErrorType (Priority: Medium)Location: ApiResponse.error(ErrorType.EXTERNAL_SERVICE_BAD_REQUEST, errors)Problem:
Recommendation: CLIENT_VALIDATION_ERROR(
HttpStatus.BAD_REQUEST, ErrorCode.E400, "요청 데이터가 유효하지 않습니다.", LogLevel.WARN)Or rename the existing type to something like: BAD_REQUEST(
HttpStatus.BAD_REQUEST, ErrorCode.E400, "잘못된 요청입니다.", LogLevel.WARN)Impact: Medium - Works functionally but creates technical debt and semantic confusion ISSUE 2: Potential ClassCastException (Priority: High)Location: e.getBindingResult().getAllErrors().forEach(error -> {
String fieldName = ((FieldError) error).getField();
String errorMessage = error.getDefaultMessage();
errors.put(fieldName, errorMessage);
});Problem:
Recommendation: e.getBindingResult().getAllErrors().forEach(error -> {
if (error instanceof FieldError fieldError) {
errors.put(fieldError.getField(), error.getDefaultMessage());
} else {
// Handle object-level errors
errors.put(error.getObjectName(), error.getDefaultMessage());
}
});Impact: High - This is a potential runtime bug that could crash the error handler itself ISSUE 3: Duplicate Field Names Silently Overwrite (Priority: Low)Location: errors.put(fieldName, errorMessage);Problem:
Recommendation: Map<String, List<String>> errors = new HashMap<>();
e.getBindingResult().getFieldErrors().forEach(error -> {
errors.computeIfAbsent(error.getField(), k -> new ArrayList<>())
.add(error.getDefaultMessage());
});Or use Spring's built-in structure (if API contract allows changes): List<ValidationError> errors = e.getBindingResult().getFieldErrors().stream()
.map(error -> new ValidationError(error.getField(), error.getDefaultMessage()))
.toList();Impact: Low - Most fields typically have single validators, but this could hide issues ISSUE 4: Overly Verbose Log Message (Priority: Low)Location: log.warn("Malformed JSON request: {}", e.getMessage());Problem:
Recommendation: log.warn("Malformed JSON request: {}",
e.getRootCause() != null ? e.getRootCause().getMessage() : e.getMessage());Or simply: log.warn("Malformed JSON request received");Impact: Low - Minor log quality issue ISSUE 5: Test Only Checks Existence, Not Value (Priority: Low)Location: .andExpect(jsonPath("$.error.data.name").exists());Problem:
Recommendation: .andExpect(jsonPath("$.error.data.name").value("이름은 필수입니다."));Impact: Low - Test could be more thorough 🔵 Performance Considerations✅ No significant performance concerns
🔒 Security Considerations✅ No security vulnerabilities identified
Minor Note:
📊 Test Coverage AnalysisCoverage Added:
Coverage Gaps:
Recommendation: @Test
@DisplayName("객체 레벨 validation 실패 시 적절한 에러 메시지를 반환한다")
void handleObjectLevelValidation() throws Exception {
// Test with @AssertTrue or similar object-level validators
}📝 Code Quality & Best Practices✅ Good Practices:
🟡 Minor Improvements:
🎯 SummaryCritical Issues (Must Fix):
Recommended Improvements:
Overall:This PR successfully closes a gap in exception handling and adds valuable test coverage. With the critical fix for the potential Estimated effort for fixes: ~30 minutes ✅ Final RecommendationAPPROVED with requested changes - Please address the Great work on identifying this gap and adding comprehensive tests! 🎉 |
Summary
MethodArgumentNotValidException,HttpMessageNotReadableException)ControllerAdviceexception handlingApiResponseformatWhat Area I Inspected
Randomly selected
src/main/java/spring/memewikibe/api/controller/ControllerAdvice.javafor maintenance review.Issues Found
Missing Validation Exception Handlers
The
ControllerAdviceclass was missing handlers for Spring's built-in validation exceptions:MethodArgumentNotValidException- thrown when@Validvalidation fails on request objects@Validwith request objects likeNotificationCreateTokenRequestwhich have validation annotations (@NotBlank,@Size)ApiResponseformatHttpMessageNotReadableException- thrown when request body contains malformed JSONNo Test Coverage
The
ControllerAdviceclass had no tests:Changes Made
1. Added Validation Exception Handlers
MethodArgumentNotValidExceptionHandler:BAD_REQUEST (400)status withErrorType.EXTERNAL_SERVICE_BAD_REQUESTHttpMessageNotReadableExceptionHandler:BAD_REQUEST (400)status2. Added Comprehensive Test Suite
Created
ControllerAdviceTestwith 4 test cases:MemeWikiApplicationExceptionhandlingTest Approach:
Why This Improves the Code
✅ Consistency: All API errors now follow the standard
ApiResponseformat✅ User Experience: Validation errors provide clear, actionable field-level feedback
✅ Maintainability: Tests ensure exception handling behavior won't regress
✅ API Design: Proper HTTP status codes and error messages for different scenarios
✅ Debugging: Better logging for validation failures and malformed requests
Testing
All existing tests pass:
New tests added:
ControllerAdviceTest(4 tests, all passing)🤖 Generated with Claude Code