본문으로 바로가기

Spring에서 request에 대한 검증 방법 2가지

category SPRING/스프링부트 2024. 5. 7. 14:53
728x90
반응형
SMALL

1. 빈값 검증, not null, 최소 사이즈와 같이 간단한 검증일땐 javax.validation의 @Valid 사용

public class TestDto {
    @Min(0)
    private int basePrice;
    @Min(0)
    private int maxPrice;
}
@Controller
@RequestMapping(value = "/api/events", produces = MediaTypes.HAL_JSON_VALUE)
public class TestController {

 @PostMapping
    public ResponseEntity createEvent(@RequestBody @Valid EventDto eventDto,
                                      Errors errors) {
        if (errors.hasErrors()) {
            return badRequest(errors);
        }
         ..
         ..
         return ResponseEntity.created(createdUri).body(eventResource);
     }

테스트는 파라미터로 들어온 TestDto 의 basePrice, maxPrice 검증이다

우리의 비즈니스 목표는 basePrice 는 maxPrice를 초과할 수 없다.

    @Test
    @DisplayName("basePrice>maxprice 면 bad request이다.")
    public void createEvent_Bad_Request_Wrong_Input() throws Exception {
        TestDto testDto = TestDto.builder()
                .basePrice(10000)
                .maxPrice(200)
                .build();

        this.mockMvc.perform(post("/api/events")
                .contentType(MediaType.APPLICATION_JSON)
                .content(this.objectMapper.writeValueAsString(testDto)))
                .andDo(print())
                .andExpect(status().isBadRequest())
                .andExpect(jsonPath("content[0].objectName").exists())
                .andExpect(jsonPath("content[0].defaultMessage").exists())
                .andExpect(jsonPath("content[0].code").exists());
    }

우리는 결과를 400을 예상했지만 비즈니스 로직은 성공적으로 진행되며 201를 뱉는다. 테스트는 실패했다.

TestDto의 basePrice > maxprice 에 대한 검증을 할 수 없기 때문이다.

 

 

2. 비즈니스 로직에 대한 구체적 검증이 필요한 경우,@Valid로는 검증이 어려운 경우, 커스텀한 validation을 만든다.

(예를 들어서 basePrice 는 maxPrice를 초과할 수 없다.)

@Component
public class EventValidator {

    public void validate(TestDto testDto, Errors errors) {
        if (testDto.getBasePrice() > testDto.getMaxPrice() && testDto.getMaxPrice() > 0) {
            errors.reject("wrongPrices", "Values fo prices are wrong");
        }
    }

}

직접 구현한 TestValidator의 메서드를 사용하자.

@Controller
@RequestMapping(value = "/api/events", produces = MediaTypes.HAL_JSON_VALUE)
public class TestController {
    private final TestValidator testValidator;

 @PostMapping
    public ResponseEntity createEvent(@RequestBody @Valid EventDto eventDto,
                                      Errors errors) {
        if (errors.hasErrors()) {
            return badRequest(errors);
        }
        //검증 한번 더!
        testValidator.validate(eventDto, errors);
        if (errors.hasErrors()) {
            return badRequest(errors);
        }

         ..
         ..
         return ResponseEntity.created(createdUri).body(eventResource);
     }   

728x90
반응형
LIST