简体   繁体   中英

@Pattern annotation is not working in junit 4

I'm working on a sample spring boot application that performs CRUD operations for the user.

I created a user API. UsersController.java is the controller code.

UsersController.java

    @PostMapping(value = "/users", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE, headers = "Authorization")
    @ApiOperation(value = "API endpoint to save users", notes = "API endpoint to save users")
    @ApiResponses(value = {
        @ApiResponse(code = 200, message = ErrorConstants.OK),
        @ApiResponse(code = 400, message = ErrorConstants.BAD_REQUEST),
        @ApiResponse(code = 403, message = ErrorConstants.FORBIDDEN),
        @ApiResponse(code = 500, message = ErrorConstants.INTERNAL_SERVER_ERROR) }
    )
    public ResponseEntity<?> addUsers(@Valid @RequestBody UserDto userDto) {
        try {
            return new ResponseEntity<>(userService.createUsers(userDto), HttpStatus.OK);
        } catch (BadRequestException e) {
            return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
        } catch (Exception e) {
            return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

DTO is as below

UserDto.java

    @JsonInclude(Include.NON_NULL)
    @JsonIgnoreProperties(ignoreUnknown = true)
    public class UserDto {
    
        private String id;
    
        @Size(min = 4, max = 36, message = "Name should be between 4 to 36 characters long.")
        @Pattern(regexp = "^[^&+;=#<>*{}@:]*$", message = "Name field Should not contain special chars")
        private String name;
    
        private String address;
        
        private String mobileNo;
    }

As you can see, I've added validation to the name field. In addition, I created a controller advise to handle the exception.

ExceptionControllerAdvise.java

    import org.springframework.web.bind.MethodArgumentNotValidException;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    
    
    @RestControllerAdvice
    public class ExceptionControllerAdvise {
    
        @ExceptionHandler(value = MethodArgumentNotValidException.class)
        public ResponseEntity<ErrorResponse> validException(MethodArgumentNotValidException exception) {
            return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
        }
    }

If any validation exceptions are raised for the annotated fields, the above class will return an error.

When I run the application and call the API with an invalid name (one that contains special characters), I get a 400 bad request exception.

But when I try to write junit test case for invalid data, the test case is passing. (ie @Pattern annotation is not working with junit)

Here is my sample junit for testing.

    @Test
    public void test0_createUsersWithInvalidName() {
        UserDto dto = new UserDto();
        dto.setName("Apple&sons!")
        dto.setAddress("abc");
        ResponseEntity<?> response = usersController.addUsers(dto)
        assertTrue(response.getStatusCode().equals(HttpStatus.BAD_REQUEST));
    }

The above test case passes, but I receive a java.lang.AssertionError error; when I debugged this issue, I discovered that I am receiving a status of 200 OK rather than 400 BAD REQUEST .

So, could anyone please assist me here? Thanks

If you want to test your bean validation rules into your controller you can do it by mocking the exception that will happen in your service class or in your integration test by the simulation of a wrong value. Also you can improve the code in your controller . Here you are returning a BAD_REQUEST in the catch section, it is the role of your ControllerAdvice class. Instead you should throw a BadRequestException request exception that will be transmitted to your ControllerAdvice .

Controller

@PostMapping(value = "/users", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE, headers = "Authorization")
@ApiOperation(value = "API endpoint to save users", notes = "API endpoint to save users")
@ApiResponses(value = {
    @ApiResponse(code = 200, message = ErrorConstants.OK),
    @ApiResponse(code = 400, message = ErrorConstants.BAD_REQUEST),
    @ApiResponse(code = 403, message = ErrorConstants.FORBIDDEN),
    @ApiResponse(code = 500, message = ErrorConstants.INTERNAL_SERVER_ERROR) }
)
public ResponseEntity<?> addUsers(@Valid @RequestBody UserDto userDto) {
    try {
        return new ResponseEntity<>(userService.createUsers(userDto), HttpStatus.OK);
    } catch (MethodArgumentNotValidException e) {
        throw new BadRequestException("YOUR MESSAGE", e); // the e in parameter to get the root cause if you send message from your validation
    } catch (Exception e) {
        throw new InternalServerErrorException("YOUR MESSAGE", e); // the e in parameter to get the root cause
    }
}

Controller Advice

@RestControllerAdvice
public class ExceptionControllerAdvise {

    @ExceptionHandler(value = BadRequestException.class)
    public ResponseEntity<ErrorResponse> validException(BadRequestException exception) {
        return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
    }

    @ExceptionHandler(value = InternalServerErrorException.class)
    public ResponseEntity<ErrorResponse> serverException(InternalServerErrorExceptionexception) {
        return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

Test class

@Test
public void test0_createUsersWithInvalidName() {
   
    ...
    
    when(userService
    .createUsers(userDto))
    .thenThrow(MethodArgumentNotValidException.class);

   ...
   // Here use mockMvc instead
}

This part of your test code will be used in your integration test:

UserDto dto = new UserDto();
dto.setName("Apple&sons!")
dto.setAddress("abc");

Also, how do you construct your ErrorResponse ?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM