프로젝트/Trouble Shooting

[Spring boot] @Valid is not working, @Valid 동작 안함

myeongju 2024. 11. 9. 22:01
반응형

@Valid를 걸고, 커스텀 어노테이션을 만들어서 코드가 실행되는 것을 확인하고, 테스트 코드로 검증을 하기 위해 테스트 코드를 작성하고 실행을 시켰다. 

커스텀 어노테이션 코드가 궁금하다면 아래 글에서 보고 오자. 

https://myeongju00.tistory.com/152

 

[Spring Boot] Custom validator annotation 만들기

API를 만들다보면 종종 클라이언트가 보낸 값을 검사하는 과정이 필요해진다. 그럴때 검증하는 로직들을 매 비즈니스 로직마다 반복적으로 넣지 말고, 어노테이션을 만들어서 사용해보도록 하

myeongju00.tistory.com

 

@Import(MockCerebrasConfig.class)
class DiaryTest extends SuperIntegrationTest {
    @Test
    void createDiary_withInvalidEmotionList() throws Exception {
        DiaryDto.DiaryRequest request = new DiaryDto.DiaryRequest(
                "사건",
                "생각",
                List.of(
                        new EmotionOfEpisodeDto(
                                EmotionType.HAPPY, List.of("행복", "즐거움", "행복", "즐거움")
                        ),
                        new EmotionOfEpisodeDto(
                                EmotionType.ANGRY, List.of("화남", "분노")
                        )
                ),
                "결과"
        );

        mvc.perform(RestDocumentationRequestBuilders
                        .post("/api/v1/diary")
                        .header(ACCEPT, APPLICATION_JSON_VALUE)
                        .header(CONTENT_TYPE, APPLICATION_JSON_VALUE)
                        .header(AUTHORIZATION, createDefaultAuthentication())
                        .content(objectMapper.writeValueAsString(request))
                        .characterEncoding("utf-8"))
                .andDo(print())
                .andExpect(status().isUnprocessableEntity())
                .andExpect(MockMvcResultMatchers.jsonPath("$.data[0].message")
                        .value("선택할 수 있는 감정은 최대 5개 입니다."))
                .andDo(document("{ClassName}" + "/" + "{methodName}",
                        requestHeaders(
                                headerWithName(ACCEPT).description("Header"),
                                headerWithName(CONTENT_TYPE).description("Content type"),
                                headerWithName(AUTHORIZATION).description("Bearer token ")
                        ),
                        requestFields(
                                fieldWithPath("episode").type(STRING).description("Episode"),
                                fieldWithPath("thoughtOfEpisode").type(STRING).description("Thought of episode"),
                                fieldWithPath("emotionOfEpisodes[].type").type(STRING).description(Arrays.toString(EmotionType.values())),
                                fieldWithPath("emotionOfEpisodes[].details").type(ARRAY).description("Details of the emotion"),
                                fieldWithPath("resultOfEpisode").type(STRING).description("Result of the episode")
                        ),
                        responseFields(
                                commonResponseFields(
                                        fieldWithPath("[].field").type(STRING).description("에러 필드(emotionOfEpisodes)"),
                                        fieldWithPath("[].message").type(STRING).description("에러 메시지")
                                )
                        ))
                );
    }
}

필자 코드는 422로 처리하게 되어있거 422를 기대하면서 테스트 코드를 돌려봤다. 하지만, 코드를 돌려보면 200이 나오는 것을 알 수 있다. 

 

이럴때는 build.gradle에 아래 문장을 추가해보자. 

implementation 'org.springframework.boot:spring-boot-starter-validation'

 

그러면 이렇게 잘 돌아가는 것을 확인할 수 있다

 

⁉️ 왜 의존성을 추가해줘야할까 ?

spring boot 2.3 version 이전에는 spring-boot-starter-web 의존성 내부에 validation 의존성이 포함돼 있었지만, 2.3 버전 이후로는 포함되지 않는다고 한다. 

 

 이 부분을 생각하지 못하고, import도 잘 되고, 실행도 잘 되어서 코드 문제인 줄 알았다. IDEA랑 import가 된다고 너무 맹신한 것이 제일 큰 문제였던 것 같다. 앞으로는 의존성도 꼼꼼하게 살펴봐야겠다..!

반응형