1- package org .opendevstack .apiservice .projectusers .exception ;
2-
1+ package org .opendevstack .apiservice .projectusers .controller .advice ;
2+ import org .junit .jupiter .api .AfterEach ;
3+ import org .junit .jupiter .api .BeforeEach ;
4+ import org .junit .jupiter .api .Test ;
5+ import org .mockito .MockitoAnnotations ;
36import org .opendevstack .apiservice .projectusers .controller .ProjectUserController ;
47import org .opendevstack .apiservice .projectusers .model .AddUserToProjectRequest ;
58import org .opendevstack .apiservice .projectusers .model .ValidationErrorResponse ;
6- import org .junit .jupiter .api .BeforeEach ;
7- import org .junit .jupiter .api .Test ;
9+ import org .springframework .core .MethodParameter ;
810import org .springframework .http .HttpStatus ;
911import org .springframework .http .ResponseEntity ;
1012import org .springframework .validation .BeanPropertyBindingResult ;
1113import org .springframework .validation .FieldError ;
1214import org .springframework .web .bind .MethodArgumentNotValidException ;
13- import org .springframework .core .MethodParameter ;
14-
1515import java .util .List ;
16-
17- import static org .junit .jupiter .api .Assertions .*;
18-
16+ import static org .junit .jupiter .api .Assertions .assertEquals ;
17+ import static org .junit .jupiter .api .Assertions .assertFalse ;
18+ import static org .junit .jupiter .api .Assertions .assertNotNull ;
19+ import static org .junit .jupiter .api .Assertions .assertTrue ;
20+ import static org .junit .jupiter .api .Assertions .fail ;
1921/**
20- * Unit test class for the GlobalExceptionHandler to verify improved validation
22+ * Unit test class for the ProjectUserExceptionHandler to verify improved validation
2123 * error messages.
2224 */
23- class GlobalExceptionHandlerTest {
24-
25- private GlobalExceptionHandler exceptionHandler ;
26-
25+ class ProjectUserExceptionHandlerTest {
26+ private ProjectUserExceptionHandler sut ;
27+ private AutoCloseable mocks ;
2728 @ BeforeEach
2829 void setUp () {
29- exceptionHandler = new GlobalExceptionHandler ();
30+ mocks = MockitoAnnotations .openMocks (this );
31+ sut = new ProjectUserExceptionHandler ();
32+ }
33+ @ AfterEach
34+ void tearDown () throws Exception {
35+ mocks .close ();
3036 }
31-
3237 @ Test
33- void testValidationErrorHandling () {
34- // Create a mock MethodArgumentNotValidException with validation errors
35- // Target object representing the @RequestBody argument
38+ void handle_method_argument_not_valid_exception_returns_bad_request_with_field_errors () {
39+ // GIVEN
3640 AddUserToProjectRequest target = new AddUserToProjectRequest ();
3741 BeanPropertyBindingResult bindingResult = new BeanPropertyBindingResult (target , "addUserToProjectRequest" );
38-
39- // Add field errors for required fields
4042 bindingResult .addError (new FieldError ("addUserToProjectRequest" , "environment" , null , false , null , null ,
4143 "Environment cannot be blank" ));
4244 bindingResult .addError (
@@ -45,45 +47,32 @@ void testValidationErrorHandling() {
4547 "Account cannot be blank" ));
4648 bindingResult .addError (
4749 new FieldError ("addUserToProjectRequest" , "role" , null , false , null , null , "Role cannot be null" ));
48-
49- // Create a MethodParameter referencing the controller method's @RequestBody
50- // parameter
5150 MethodParameter methodParameter ;
5251 try {
5352 methodParameter = new MethodParameter (
5453 ProjectUserController .class .getMethod (
5554 "triggerMembershipRequest" , String .class , AddUserToProjectRequest .class ),
56- 1 // index of AddUserToProjectRequest parameter
57- );
55+ 1 );
5856 } catch (NoSuchMethodException e ) {
5957 fail ("Failed to reflect controller method for test: " + e .getMessage ());
60- return ; // unreachable, but required for compilation
58+ return ;
6159 }
62-
6360 MethodArgumentNotValidException exception = new MethodArgumentNotValidException (methodParameter , bindingResult );
64-
65- // Test the exception handler
66- ResponseEntity <ValidationErrorResponse > response = exceptionHandler
67- .handleMethodArgumentNotValidException (exception );
68-
69- // Verify response
61+ // WHEN
62+ ResponseEntity <ValidationErrorResponse > response = sut .handleMethodArgumentNotValidException (exception );
63+ // THEN
7064 assertEquals (HttpStatus .BAD_REQUEST , response .getStatusCode ());
7165 assertNotNull (response .getBody ());
72-
7366 ValidationErrorResponse errorResponse = response .getBody ();
7467 assertFalse (errorResponse .getSuccess ());
7568 assertEquals ("PROJECT_USER_ERROR" , errorResponse .getErrorCode ());
7669 assertNotNull (errorResponse .getFieldErrors ());
7770 assertEquals (4 , errorResponse .getFieldErrors ().size ());
78-
79- // Check specific field errors
8071 List <org .opendevstack .apiservice .projectusers .model .FieldError > fieldErrors = errorResponse .getFieldErrors ();
8172 assertTrue (fieldErrors .stream ().anyMatch (error -> "environment" .equals (error .getField ())));
8273 assertTrue (fieldErrors .stream ().anyMatch (error -> "user" .equals (error .getField ())));
8374 assertTrue (fieldErrors .stream ().anyMatch (error -> "account" .equals (error .getField ())));
8475 assertTrue (fieldErrors .stream ().anyMatch (error -> "role" .equals (error .getField ())));
85-
86- // Verify expected format is provided for each field
8776 fieldErrors .forEach (fieldError -> {
8877 assertNotNull (fieldError .getField ());
8978 assertNotNull (fieldError .getMessage ());
@@ -93,15 +82,14 @@ void testValidationErrorHandling() {
9382 }
9483 });
9584 }
96-
9785 @ Test
98- void testGenericExceptionHandling () {
99- // Test generic exception handling
86+ void handle_generic_exception_returns_internal_server_error () {
87+ // GIVEN
10088 Exception exception = new RuntimeException ("Unexpected error" );
101-
102- ResponseEntity <?> response = exceptionHandler .handleGenericException (exception );
103-
89+ // WHEN
90+ ResponseEntity <?> response = sut .handleGenericException (exception );
91+ // THEN
10492 assertEquals (HttpStatus .INTERNAL_SERVER_ERROR , response .getStatusCode ());
10593 assertNotNull (response .getBody ());
10694 }
107- }
95+ }
0 commit comments