본문 바로가기
스프링

[스프링] @Valid 사용과 테스트 케이스 작성하기

by kdohyeon (김대니) 2023. 2. 6.
반응형

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("키워드를 입력하세요.");
        });
    }
}

 

반응형

댓글