Skip to content

Commit 936b058

Browse files
authored
RA-91: The error message has been expanded + UTs have been added (#163)
2 parents 4358c96 + 3dcf2aa commit 936b058

File tree

2 files changed

+108
-20
lines changed

2 files changed

+108
-20
lines changed

api/src/main/java/org/cardanofoundation/rosetta/common/exception/GlobalExceptionHandler.java

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,55 +3,44 @@
33
import java.util.List;
44
import jakarta.servlet.http.HttpServletRequest;
55

6-
import org.springframework.beans.factory.annotation.Value;
76
import org.springframework.http.HttpStatus;
87
import org.springframework.http.ResponseEntity;
9-
import org.springframework.validation.FieldError;
108
import org.springframework.web.bind.MethodArgumentNotValidException;
11-
import org.springframework.web.bind.annotation.ControllerAdvice;
129
import org.springframework.web.bind.annotation.ExceptionHandler;
10+
import org.springframework.web.bind.annotation.RestControllerAdvice;
1311

1412
import org.cardanofoundation.rosetta.common.util.RosettaConstants.RosettaErrorType;
1513

16-
@ControllerAdvice
14+
@RestControllerAdvice
1715
public class GlobalExceptionHandler {
1816

19-
@Value("${api.exception.isPrintStackTrace:true}")
20-
private String isPrintStackTrace;
21-
22-
2317
@ExceptionHandler(Exception.class)
2418
public ResponseEntity<Error> handleGlobalException(Exception exception,
2519
HttpServletRequest request) {
26-
printStackTraceIfNeeded(exception);
20+
2721
Error errorResponse = RosettaErrorType.UNSPECIFIED_ERROR.toRosettaError(true,
2822
new Details("An error occurred for request " + request.getRequestId() + ": "
29-
+ exception.getMessage()));
23+
+ exception.getMessage()));
3024

3125
return new ResponseEntity<>(errorResponse, HttpStatus.INTERNAL_SERVER_ERROR);
3226
}
3327

3428
@ExceptionHandler(ApiException.class)
3529
public ResponseEntity<Error> handleApiException(ApiException apiException) {
36-
printStackTraceIfNeeded(apiException);
3730
return new ResponseEntity<>(apiException.getError(), HttpStatus.INTERNAL_SERVER_ERROR);
3831
}
3932

4033
@ExceptionHandler(MethodArgumentNotValidException.class)
4134
public ResponseEntity<Error> handleMethodArgumentNotValidException(
4235
MethodArgumentNotValidException methodArgumentNotValidException, HttpServletRequest request) {
43-
printStackTraceIfNeeded(methodArgumentNotValidException);
36+
4437
List<String> errors = methodArgumentNotValidException.getBindingResult().getFieldErrors()
45-
.stream().map(FieldError::getDefaultMessage).toList();
38+
.stream()
39+
.map(error -> error.getField() + " " + error.getDefaultMessage())
40+
.toList();
4641
Error errorResponse = RosettaErrorType.UNSPECIFIED_ERROR.toRosettaError(true,
4742
new Details("An error occurred for request " + request.getRequestId() + ": "
48-
+ errors));
43+
+ errors));
4944
return new ResponseEntity<>(errorResponse, HttpStatus.INTERNAL_SERVER_ERROR);
5045
}
51-
52-
private void printStackTraceIfNeeded(Exception exception) {
53-
if (isPrintStackTrace.equals("true")) {
54-
exception.printStackTrace();
55-
}
56-
}
5746
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
package org.cardanofoundation.rosetta.common.exception;
2+
3+
import java.util.Collections;
4+
import jakarta.servlet.http.HttpServletRequest;
5+
6+
import org.springframework.http.HttpStatus;
7+
import org.springframework.http.ResponseEntity;
8+
import org.springframework.validation.BindingResult;
9+
import org.springframework.validation.FieldError;
10+
import org.springframework.web.bind.MethodArgumentNotValidException;
11+
import org.mockito.InjectMocks;
12+
import org.mockito.Mock;
13+
import org.mockito.junit.jupiter.MockitoExtension;
14+
15+
import org.junit.jupiter.api.Test;
16+
import org.junit.jupiter.api.extension.ExtendWith;
17+
18+
import org.cardanofoundation.rosetta.common.util.RosettaConstants.RosettaErrorType;
19+
20+
import static org.junit.jupiter.api.Assertions.assertEquals;
21+
import static org.mockito.Mockito.when;
22+
23+
@ExtendWith(MockitoExtension.class)
24+
class GlobalExceptionHandlerTest {
25+
26+
private static final String TEST_ID = "1";
27+
private static final Integer CARDANO_ERROR_CODE = 5000;
28+
private static final String FIELD_NAME = "fieldName";
29+
private static final String MISSING_FIELD_MESSAGE = "must be not null";
30+
private static final String ARGUMENT_NOT_VALID_MESSAGE = FIELD_NAME + " " + MISSING_FIELD_MESSAGE;
31+
private static final String GLOBAL_MESSAGE = "Global Exception";
32+
private static final String API_MESSAGE = "API Exception";
33+
private static final String GLOBAL_EXCEPTION_MESSAGE =
34+
"An error occurred for request " + TEST_ID + ": " + GLOBAL_MESSAGE;
35+
private static final String API_EXCEPTION_MESSAGE =
36+
"An error occurred for request " + TEST_ID + ": " + API_MESSAGE;
37+
private static final String ARGUMENT_NOT_VALID_EXCEPTION_MESSAGE =
38+
"An error occurred for request " + TEST_ID + ": [" + ARGUMENT_NOT_VALID_MESSAGE + "]";
39+
40+
@Mock
41+
private HttpServletRequest request;
42+
43+
@Mock
44+
private MethodArgumentNotValidException methodArgumentNotValidException;
45+
46+
@Mock
47+
private FieldError fieldError;
48+
49+
@Mock
50+
private BindingResult bindingResult;
51+
52+
@InjectMocks
53+
private GlobalExceptionHandler underTest;
54+
55+
@Test
56+
void handleGlobalException_shouldReturnInternalServerError() {
57+
Exception globalException = new Exception(GLOBAL_MESSAGE);
58+
59+
when(request.getRequestId()).thenReturn(TEST_ID);
60+
ResponseEntity<Error> result = underTest.handleGlobalException(globalException, request);
61+
62+
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, result.getStatusCode());
63+
assertEquals(GLOBAL_EXCEPTION_MESSAGE, result.getBody().getDetails().getMessage());
64+
assertEquals(CARDANO_ERROR_CODE, result.getBody().getCode());
65+
}
66+
67+
@Test
68+
void handleAPIException_shouldReturnInternalServerError() {
69+
ApiException apiException = createApiException();
70+
71+
ResponseEntity<Error> result = underTest.handleApiException(apiException);
72+
73+
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, result.getStatusCode());
74+
assertEquals(apiException.getError().getDetails().getMessage(),
75+
result.getBody().getDetails().getMessage());
76+
assertEquals(apiException.getError().getCode(), result.getBody().getCode());
77+
}
78+
79+
@Test
80+
void handleMethodArgumentNotValidException_shouldReturnInternalServerError() {
81+
when(methodArgumentNotValidException.getBindingResult()).thenReturn(bindingResult);
82+
when(bindingResult.getFieldErrors()).thenReturn(Collections.singletonList(fieldError));
83+
when(fieldError.getField()).thenReturn(FIELD_NAME);
84+
when(fieldError.getDefaultMessage()).thenReturn(MISSING_FIELD_MESSAGE);
85+
when(request.getRequestId()).thenReturn(TEST_ID);
86+
87+
ResponseEntity<Error> result = underTest.handleMethodArgumentNotValidException(
88+
methodArgumentNotValidException, request);
89+
90+
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, result.getStatusCode());
91+
assertEquals(ARGUMENT_NOT_VALID_EXCEPTION_MESSAGE, result.getBody().getDetails().getMessage());
92+
assertEquals(CARDANO_ERROR_CODE, result.getBody().getCode());
93+
}
94+
95+
private ApiException createApiException() {
96+
return new ApiException(RosettaErrorType.UNSPECIFIED_ERROR.toRosettaError(true,
97+
new Details(API_EXCEPTION_MESSAGE)));
98+
}
99+
}

0 commit comments

Comments
 (0)