환경
스프링 부트 2.x
의 환경을 기준으로 한다.
의존성 설치하기
- 스프링 부트 버전에 맞는
spring-boot-starter-validation
의존성을 설치한다.
의존성의 설치는 빌드 도구에 따라 다르다. maven
, gradle
등 각 도구에 맞게 설치해주자.
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-validation'
}
객체에 애노테이션 추가하기
javax.validation.constraints
에 있는 애노테이션을 사용한다.
public class MeetupCreationDto {
@NotBlank(message = "모임의 이름을 입력해주세요.")
private String name;
@Range(min = 1, max = 1000, message = "모임의 정원은 최소 1명 이상이어야 합니다.")
private int capacity;
@NotBlank(message = "모임 장소를 입력해주세요.")
private String place;
@NotBlank(message = "최소 1명 이상 참석해야 합니다.")
private String joinUsers;
@Future(message = "모임 시작 시간은 과거일 수 없습니다.")
private LocalDateTime startTime;
@Future(message = "모임 종료 시간은 과거일 수 없습니다.")
private LocalDateTime endTime;
}
예제로 위와 같이 의존성을 추가해보았다.
컨트롤러에 적용시키기
@PostMapping("")
@ResponseStatus(HttpStatus.CREATED)
public MeetupResponseDto create(@Valid @RequestBody MeetupCreationDto dto) {
return modelMapper.map(meetupService.create(dto), MeetupResponseDto.class);
}
위에서 핵심은 @Valid
애노테이션이 @RequestBody
앞에 추가된 것이다. dto
에 매핑되는 객체가 Validator
에 의해 검증받게 해준다.
개인적으로 객체에 Bean Validation 을 적용한 뒤에
@Valid
애노테이션을 추가하지 않고 Bean Validation 이 왜 적용이 안되는지 고민한적이 꽤 있었다. 이런 실수에 주의하자.
테스트하기
Java Bean Validation 을 테스트하는 방법에는 2가지 종류가 있다. 먼저, MockMvc 를 통해 Api 자체를 테스트할 수도 있고, 그냥 자바 환경에서 유닛테스트처럼 테스트할 수도 있다.
API 테스트
Advice
설정하기
@RestControllerAdvice
public class BeanValidationControllerAdvice {
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(MethodArgumentNotValidException.class)
public ErrorResponseDto handleMethodArgumentNotValidException(
MethodArgumentNotValidException exception
) {
return new ValidationErrorResponseDto(HttpStatus.BAD_REQUEST, MethodArgumentNotValidException.class.getName(), "입력 데이터 검증 오류가 발생하였습니다.", exception.getFieldErrors());
}
}
MethodArgumentNotValidException
이 발생하면, 자체적으로 정의한 ValidationErrorResponseDto
객체를 생성하여 반환하도록 하였다.
MockMvc
를 통한 API 날려보기
@Nested
@DisplayName("유효하지 않은 Meetup 정보 JSON 을 받는다면")
class Context_not_valid_meetup_data {
private final MockHttpServletRequestBuilder requestBuilder;
private final ResultActions resultActions;
public Context_not_valid_meetup_data() throws Exception {
meetupJpaRepository.deleteAll();
requestBuilder = post(rootPath);
String json = "{\"name\":\"\",\"capacity\":5,\"place\":\"서울\",\"joinUsers\":\"JakeSeo\",\"startTime\":\"2022-05-22 06:32:00\",\"endTime\":\"2022-05-22 11:20:00\"}";
requestBuilder
.content(json)
.contentType(MediaType.APPLICATION_JSON);
resultActions = mockMvc.perform(requestBuilder);
}
@Test
@DisplayName("400 BAD REQUEST 코드로 응답한다.")
void it_responses_400_bad_request() throws Exception {
resultActions.andExpect(status().isBadRequest());
}
}
스프링에서 자체적으로 제공하는 mockMvc
를 통해 테스트해볼 수 있다.
자바 테스트
@DisplayName("Java EE Validation 적용")
public class ValidationTest {
private Validator validator;
@BeforeEach
void setUp() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@Nested
@DisplayName("Validator 는")
class Describe_validator {
@Nested
@DisplayName("검증 애노테이션을 가진 필드가 있는 클래스가 있을 때")
class Context_with_class_having_field_containing_validation_annotations{
@Test
@DisplayName("객체를 검증하고, Set<ConstraintViolation> 을 반환한다.")
void it_returns_set_of_constraint_violation() {
MeetupCreationDto meetupCreationDto = MeetupCreationDto.builder().name("").build();
Set<ConstraintViolation<MeetupCreationDto>> violations = validator.validate(meetupCreationDto);
Assertions.assertThat(violations).isNotNull();
Assertions.assertThat(violations.size()).isNotZero();
for (ConstraintViolation<MeetupCreationDto> violation : violations) {
String message = violation.getMessage();
System.out.println("message = " + message);
Path propertyPath = violation.getPropertyPath();
System.out.println("propertyPath = " + propertyPath);
Class<MeetupCreationDto> rootBeanClass = violation.getRootBeanClass();
System.out.println("rootBeanClass = " + rootBeanClass);
String messageTemplate = violation.getMessageTemplate();
System.out.println("messageTemplate = " + messageTemplate);
}
}
}
}
}
서버를 켜지 않고 유닛테스트처럼 정상적으로 검증이 되는지 테스트해볼 수 있다.
위 Bean Validation 테스트 코드에서 알아볼 수 있는 사실은 검증이 Validator
라는 검증용 객체가 진행한다는 것을 알 수 있다.
이 Validator
라는 검증용 객체는 hibernate
에서 제공한다. (아래의 읽어볼만한 자료에서 제공하는 링크를 읽어보자.)
읽어볼만한 자료
'프레임워크 > 스프링 프레임워크' 카테고리의 다른 글
스프링 프레임워크 버전 4.2에서 4.3 업그레이드시 변화사항 (0) | 2023.03.23 |
---|---|
DispatchServlet.doDispatch() 함수 끝까지 따라가서 HandlerMapping 과 HandlerAdapter 알아보기 (0) | 2023.01.30 |
asciidoctor 를 통한 Spring REST Docs 자동 생성 세팅하기 (2) | 2022.05.18 |
Spring REST Docs + asciidoctor 로 문서 자동 생성해보기 (0) | 2022.05.15 |
AutoConfigureMockMvc 에서 한글이 제대로 인식되지 않을 때 (0) | 2022.04.03 |