From 139ce773c5b5e94bc86ac33105af6901ac34ad4f Mon Sep 17 00:00:00 2001 From: Bruno Silva Date: Sat, 29 Aug 2026 23:07:39 -0300 Subject: [PATCH 1/2] =?UTF-8?q?Adicionar=20handler=20gen=C3=A9rico=20de=20?= =?UTF-8?q?exce=C3=A7=C3=B5es=20n=C3=A3o=20mapeadas=20(#46)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Novo record ErrorResponse para respostas padronizadas de erro - @ExceptionHandler(Exception.class) em ControllerExceptionHandler retornando 500 com mensagem genérica, sem expor stacktrace - Loga a exceção completa via @Slf4j para diagnóstico no servidor - Testes cobrindo o novo handler e os handlers específicos existentes Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../exception/ControllerExceptionHandler.java | 10 ++++ .../exception/ErrorResponse.java | 6 ++ .../ControllerExceptionHandlerTest.java | 55 +++++++++++++++++++ 3 files changed, 71 insertions(+) create mode 100644 src/main/java/com/bts/personalbudget/exception/ErrorResponse.java create mode 100644 src/test/java/com/bts/personalbudget/exception/ControllerExceptionHandlerTest.java diff --git a/src/main/java/com/bts/personalbudget/exception/ControllerExceptionHandler.java b/src/main/java/com/bts/personalbudget/exception/ControllerExceptionHandler.java index 6bd9fb4..fc240ff 100644 --- a/src/main/java/com/bts/personalbudget/exception/ControllerExceptionHandler.java +++ b/src/main/java/com/bts/personalbudget/exception/ControllerExceptionHandler.java @@ -11,6 +11,7 @@ import java.util.List; import java.util.Map; import java.util.Optional; +import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.http.converter.HttpMessageNotReadableException; @@ -22,6 +23,7 @@ import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException; +@Slf4j @RestControllerAdvice public class ControllerExceptionHandler { @@ -94,4 +96,12 @@ public ResponseEntity handlerFolderNotFoundException(MethodA HttpStatus.BAD_REQUEST); } + @ExceptionHandler(Exception.class) + public ResponseEntity handleGenericException(Exception exception) { + log.error("m=handleGenericException, message={}", exception.getMessage(), exception); + return new ResponseEntity<>( + new ErrorResponse("Erro interno no servidor"), + HttpStatus.INTERNAL_SERVER_ERROR); + } + } diff --git a/src/main/java/com/bts/personalbudget/exception/ErrorResponse.java b/src/main/java/com/bts/personalbudget/exception/ErrorResponse.java new file mode 100644 index 0000000..99486d9 --- /dev/null +++ b/src/main/java/com/bts/personalbudget/exception/ErrorResponse.java @@ -0,0 +1,6 @@ +package com.bts.personalbudget.exception; + +public record ErrorResponse( + String message +) { +} diff --git a/src/test/java/com/bts/personalbudget/exception/ControllerExceptionHandlerTest.java b/src/test/java/com/bts/personalbudget/exception/ControllerExceptionHandlerTest.java new file mode 100644 index 0000000..55fde4c --- /dev/null +++ b/src/test/java/com/bts/personalbudget/exception/ControllerExceptionHandlerTest.java @@ -0,0 +1,55 @@ +package com.bts.personalbudget.exception; + +import com.bts.personalbudget.controller.validation.ValidationResponse; +import java.util.Map; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.MissingServletRequestParameterException; +import static org.assertj.core.api.Assertions.assertThat; + +class ControllerExceptionHandlerTest { + + private final ControllerExceptionHandler handler = new ControllerExceptionHandler(); + + @Test + @DisplayName("Deve retornar 500 com mensagem genérica para exceção não mapeada") + void shouldHandleGenericException() { + final RuntimeException exception = new RuntimeException("erro interno inesperado, com dados sensíveis"); + + final ResponseEntity response = handler.handleGenericException(exception); + + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR); + assertThat(response.getBody()).isNotNull(); + assertThat(response.getBody().message()).isEqualTo("Erro interno no servidor"); + assertThat(response.getBody().message()).doesNotContain("dados sensíveis"); + } + + @Test + @DisplayName("Handler específico de InvalidFieldsException deve continuar funcionando sem regressão") + void shouldStillHandleInvalidFieldsExceptionSpecifically() { + final InvalidFieldsException exception = new InvalidFieldsException( + "Campos inválidos", String.class, Map.of("campo", "mensagem")); + + final ResponseEntity response = handler.handleJsonErrors(exception); + + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST); + assertThat(response.getBody()).isNotNull(); + assertThat(response.getBody().validations()).containsEntry("campo", "mensagem"); + } + + @Test + @DisplayName("Handler específico de MissingServletRequestParameterException deve continuar funcionando sem regressão") + void shouldStillHandleMissingParameterExceptionSpecifically() { + final MissingServletRequestParameterException exception = + new MissingServletRequestParameterException("param", "String"); + + final ResponseEntity response = handler.handlerFolderNotFoundException(exception); + + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST); + assertThat(response.getBody()).isNotNull(); + assertThat(response.getBody().validations()).containsKey("param"); + } + +} From 7f2330e487d075583e244a5d0b2be94f14493573 Mon Sep 17 00:00:00 2001 From: Bruno Silva Date: Sat, 29 Aug 2026 23:17:24 -0300 Subject: [PATCH 2/2] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../exception/ControllerExceptionHandlerTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/bts/personalbudget/exception/ControllerExceptionHandlerTest.java b/src/test/java/com/bts/personalbudget/exception/ControllerExceptionHandlerTest.java index 55fde4c..3b2188b 100644 --- a/src/test/java/com/bts/personalbudget/exception/ControllerExceptionHandlerTest.java +++ b/src/test/java/com/bts/personalbudget/exception/ControllerExceptionHandlerTest.java @@ -27,8 +27,8 @@ void shouldHandleGenericException() { } @Test - @DisplayName("Handler específico de InvalidFieldsException deve continuar funcionando sem regressão") - void shouldStillHandleInvalidFieldsExceptionSpecifically() { + @DisplayName("Deve retornar 400 para InvalidFieldsException") + void shouldReturnBadRequestForInvalidFieldsException() { final InvalidFieldsException exception = new InvalidFieldsException( "Campos inválidos", String.class, Map.of("campo", "mensagem"));