1
+ package com .springbootmicroservices .productservice .exception ;
2
+
3
+ import com .springbootmicroservices .productservice .base .AbstractRestControllerTest ;
4
+ import com .springbootmicroservices .productservice .model .common .CustomError ;
5
+ import jakarta .validation .ConstraintViolation ;
6
+ import jakarta .validation .ConstraintViolationException ;
7
+ import jakarta .validation .Path ;
8
+ import org .junit .jupiter .api .Test ;
9
+ import org .mockito .InjectMocks ;
10
+ import org .springframework .http .HttpStatus ;
11
+ import org .springframework .http .ResponseEntity ;
12
+ import org .springframework .validation .BindingResult ;
13
+ import org .springframework .validation .FieldError ;
14
+ import org .springframework .validation .ObjectError ;
15
+ import org .springframework .web .bind .MethodArgumentNotValidException ;
16
+
17
+ import java .time .LocalDateTime ;
18
+ import java .util .Collections ;
19
+ import java .util .List ;
20
+ import java .util .Set ;
21
+
22
+ import static org .assertj .core .api .Assertions .assertThat ;
23
+ import static org .junit .jupiter .api .Assertions .*;
24
+ import static org .mockito .Mockito .mock ;
25
+ import static org .mockito .Mockito .when ;
26
+
27
+ class GlobalExceptionHandlerTest extends AbstractRestControllerTest {
28
+
29
+ @ InjectMocks
30
+ private GlobalExceptionHandler globalExceptionHandler ;
31
+
32
+ @ Test
33
+ void givenMethodArgumentNotValidException_whenHandleMethodArgumentNotValid_thenRespondWithBadRequest () {
34
+
35
+ // Given
36
+ BindingResult bindingResult = mock (BindingResult .class );
37
+ MethodArgumentNotValidException ex = new MethodArgumentNotValidException (null , bindingResult );
38
+ FieldError fieldError = new FieldError ("objectName" , "fieldName" , "error message" );
39
+ List <ObjectError > objectErrors = Collections .singletonList (fieldError );
40
+
41
+ when (bindingResult .getAllErrors ()).thenReturn (objectErrors );
42
+
43
+ CustomError expectedError = CustomError .builder ()
44
+ .httpStatus (HttpStatus .BAD_REQUEST )
45
+ .header (CustomError .Header .VALIDATION_ERROR .getName ())
46
+ .message ("Validation failed" )
47
+ .subErrors (Collections .singletonList (
48
+ CustomError .CustomSubError .builder ()
49
+ .field ("fieldName" )
50
+ .message ("error message" )
51
+ .build ()))
52
+ .build ();
53
+
54
+ // When
55
+ ResponseEntity <Object > responseEntity = globalExceptionHandler .handleMethodArgumentNotValid (ex );
56
+
57
+ // Then
58
+ assertThat (responseEntity .getStatusCode ()).isEqualTo (HttpStatus .BAD_REQUEST );
59
+ CustomError actualError = (CustomError ) responseEntity .getBody ();
60
+ checkCustomError (expectedError , actualError );
61
+
62
+ }
63
+
64
+ @ Test
65
+ void givenConstraintViolationException_whenHandlePathVariableErrors_thenRespondWithBadRequest () {
66
+
67
+ // Given
68
+ ConstraintViolation <String > mockViolation = mock (ConstraintViolation .class );
69
+ Path mockPath = mock (Path .class );
70
+ Set <ConstraintViolation <?>> violations = Set .of (mockViolation );
71
+ ConstraintViolationException mockException = new ConstraintViolationException (violations );
72
+
73
+ CustomError .CustomSubError subError = CustomError .CustomSubError .builder ()
74
+ .message ("must not be null" )
75
+ .field ("" )
76
+ .value ("invalid value" )
77
+ .type ("String" ) // Default to String if getRootBeanClass() is null
78
+ .build ();
79
+
80
+ CustomError expectedError = CustomError .builder ()
81
+ .time (LocalDateTime .now ())
82
+ .httpStatus (HttpStatus .BAD_REQUEST )
83
+ .header (CustomError .Header .VALIDATION_ERROR .getName ())
84
+ .message ("Constraint violation" )
85
+ .subErrors (Collections .singletonList (subError ))
86
+ .build ();
87
+
88
+ // When
89
+ when (mockViolation .getMessage ()).thenReturn ("must not be null" );
90
+ when (mockViolation .getPropertyPath ()).thenReturn (mockPath );
91
+ when (mockPath .toString ()).thenReturn ("field" );
92
+ when (mockViolation .getInvalidValue ()).thenReturn ("invalid value" );
93
+ when (mockViolation .getRootBeanClass ()).thenReturn (String .class ); // Ensure this does not return null
94
+
95
+ // Then
96
+ ResponseEntity <Object > responseEntity = globalExceptionHandler .handlePathVariableErrors (mockException );
97
+
98
+ CustomError actualError = (CustomError ) responseEntity .getBody ();
99
+
100
+ // Verify
101
+ checkCustomError (expectedError , actualError );
102
+
103
+ }
104
+
105
+ @ Test
106
+ void givenRuntimeException_whenHandleRuntimeException_thenRespondWithNotFound () {
107
+
108
+ // Given
109
+ RuntimeException ex = new RuntimeException ("Runtime exception message" );
110
+
111
+ CustomError expectedError = CustomError .builder ()
112
+ .httpStatus (HttpStatus .NOT_FOUND )
113
+ .header (CustomError .Header .API_ERROR .getName ())
114
+ .message ("Runtime exception message" )
115
+ .build ();
116
+
117
+ // When
118
+ ResponseEntity <?> responseEntity = globalExceptionHandler .handleRuntimeException (ex );
119
+
120
+ // Then
121
+ assertThat (responseEntity .getStatusCode ()).isEqualTo (HttpStatus .NOT_FOUND );
122
+
123
+ CustomError actualError = (CustomError ) responseEntity .getBody ();
124
+ checkCustomError (expectedError , actualError );
125
+
126
+ }
127
+
128
+ @ Test
129
+ void givenProductAlreadyExistException_whenHandleProductAlreadyExistException_thenRespondWithConflict () {
130
+
131
+ // Given
132
+ ProductAlreadyExistException ex = new ProductAlreadyExistException ();
133
+
134
+ CustomError expectedError = CustomError .builder ()
135
+ .httpStatus (HttpStatus .CONFLICT )
136
+ .header (CustomError .Header .ALREADY_EXIST .getName ())
137
+ .message ("Product already exist!\n " )
138
+ .isSuccess (false )
139
+ .build ();
140
+
141
+ // When
142
+ ResponseEntity <CustomError > responseEntity = globalExceptionHandler .handleProductAlreadyExistException (ex );
143
+
144
+ // Then
145
+ assertThat (responseEntity .getStatusCode ()).isEqualTo (HttpStatus .CONFLICT );
146
+
147
+ CustomError actualError = responseEntity .getBody ();
148
+ checkCustomError (expectedError , actualError );
149
+
150
+ }
151
+
152
+ @ Test
153
+ void givenProductNotFoundException_whenHandleProductNotFoundException_thenRespondWithNotFound () {
154
+
155
+ // Given
156
+ ProductNotFoundException ex = new ProductNotFoundException ();
157
+
158
+ CustomError expectedError = CustomError .builder ()
159
+ .httpStatus (HttpStatus .NOT_FOUND )
160
+ .header (CustomError .Header .NOT_FOUND .getName ())
161
+ .message ("Product not found!\n " )
162
+ .isSuccess (false )
163
+ .build ();
164
+
165
+ // When
166
+ ResponseEntity <CustomError > responseEntity = globalExceptionHandler .handleProductNotFoundException (ex );
167
+
168
+ // Then
169
+ assertThat (responseEntity .getStatusCode ()).isEqualTo (HttpStatus .NOT_FOUND );
170
+
171
+ CustomError actualError = responseEntity .getBody ();
172
+ checkCustomError (expectedError , actualError );
173
+ }
174
+
175
+
176
+
177
+ private void checkCustomError (CustomError expectedError , CustomError actualError ) {
178
+
179
+ assertThat (actualError ).isNotNull ();
180
+ assertThat (actualError .getTime ()).isNotNull ();
181
+ assertThat (actualError .getHeader ()).isEqualTo (expectedError .getHeader ());
182
+ assertThat (actualError .getIsSuccess ()).isEqualTo (expectedError .getIsSuccess ());
183
+
184
+ if (expectedError .getMessage () != null ) {
185
+ assertThat (actualError .getMessage ()).isEqualTo (expectedError .getMessage ());
186
+ }
187
+
188
+ if (expectedError .getSubErrors () != null ) {
189
+ assertThat (actualError .getSubErrors ().size ()).isEqualTo (expectedError .getSubErrors ().size ());
190
+ if (!expectedError .getSubErrors ().isEmpty ()) {
191
+ assertThat (actualError .getSubErrors ().get (0 ).getMessage ()).isEqualTo (expectedError .getSubErrors ().get (0 ).getMessage ());
192
+ assertThat (actualError .getSubErrors ().get (0 ).getField ()).isEqualTo (expectedError .getSubErrors ().get (0 ).getField ());
193
+ assertThat (actualError .getSubErrors ().get (0 ).getValue ()).isEqualTo (expectedError .getSubErrors ().get (0 ).getValue ());
194
+ assertThat (actualError .getSubErrors ().get (0 ).getType ()).isEqualTo (expectedError .getSubErrors ().get (0 ).getType ());
195
+ }
196
+ }
197
+ }
198
+
199
+ }
0 commit comments