반응형
RestController 에서 @RequestBody 등을 통해 데이터를 받을 때, 유효성 검증을 위해 @Valid 어노테이션을 주로 사용한다. 필수 값이 입력되어 있는지, 숫자 값의 boundary 내에 포함되어 있는지, 문자열의 길이가 유효한지 등을 확인할 수 있다.
의존성 추가
아래 의존성을 추가하면 @Valid 어노테이션을 사용해서 유효성 검증을 할 수 있다.
implementation 'org.springframework.boot:spring-boot-starter-validation'
활용 방법
아래 컨트롤러의 SearchBlogRequestBody 부분을 보면 객체 앞부분에 @Valid 어노테이션이 부여되어 있다.
@RestController
public class BlogSearchController {
private final SearchBlogUseCase searchBlogUseCase;
public BlogSearchController(SearchBlogUseCase searchBlogUseCase) {
this.searchBlogUseCase = searchBlogUseCase;
}
@GetMapping("/api/v1/blogs")
public ResultResponse<BlogDto> searchBlogs(
@Valid SearchBlogRequestBody requestBody,
@RequestParam(required = false, defaultValue = "1") int page,
@RequestParam(required = false, defaultValue = "10") int size
) {
var command = BlogSearchCommand.builder()
.keyword(requestBody.getKeyword())
.url(requestBody.getUrl())
.sort(requestBody.getSort())
.page(page) // db 조회였다면 pageable 를 사용했을텐데 외부 API 호출이라 굳이 사용하지 않음
.size(size)
.build();
return ResultResponse.ok(searchBlogUseCase.search(command));
}
}
SearchBlogRequestBody 를 살펴보자. 3개의 필드가 존재하고 keyword 필드에 대해서는 @NotBlank 어노테이션이 부여되어 있다. 만약 keyword 필드에 대한 값이 null 또는 빈 문자열 ("") 으로 입력되면 @Valid 어노테이션에 의해 객체 생성에 실패하면서 예외가 발생하게 된다.
@Getter
public class SearchBlogRequestBody {
@NotBlank(message = "키워드를 입력하세요.")
private final String keyword;
private final String url;
private final BlogSearchQuerySort sort;
@ConstructorProperties({"keyword", "url", "sort"})
public SearchBlogRequestBody(String keyword, String url, BlogSearchQuerySort sort) {
this.keyword = keyword;
this.url = url;
this.sort = sort;
}
}
만약 유효하지 않은 요청을 보내게 되면 아래처럼 예외가 발생하게 된다.
테스트 코드 작성
이 코드에 대한 테스트는 어떻게 할 수 있을까?
class SearchBlogRequestBodyTest {
private static ValidatorFactory factory;
private static Validator validator;
@BeforeAll
public static void init() {
factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
@AfterAll
public static void close() {
factory.close();
}
@DisplayName("블로그 검색을 하기 위해서는 keyword 는 필수이다.")
@Test
void keywordIsMandatory() {
// given
SearchBlogRequestBody request = new SearchBlogRequestBody(null, null, null);
// then
Set<ConstraintViolation<SearchBlogRequestBody>> violations = validator.validate(request);
// then
assertThat(violations).isNotEmpty();
violations.forEach(error -> {
assertThat(error.getMessage()).isEqualTo("키워드를 입력하세요.");
});
}
}
반응형
'스프링' 카테고리의 다른 글
[스프링] H2 데이터베이스 사용하기 (0) | 2023.02.09 |
---|---|
[스프링] 멀티 모듈 환경에서 application.yml 사용하기 (0) | 2023.02.09 |
[스프링] REST Docs, asciidoctor 로 API 문서 관리하기 (0) | 2023.02.06 |
[스프링] JPA 관련 통합 테스트 환경 구축하기 (0) | 2023.02.06 |
[스프링] JUnit5, AssertJ, Mockito 기반 테스트 환경 구축하기 (0) | 2023.02.06 |
댓글