💐 Spring/Spring REST API

5) [test] 입력값 제한하기 (비즈니스 로직으로 검사) - 스프링 REST API

2020. 9. 10. 09:41
목차
  1. 도메인 Validator 만들기
  2. Controller 에서 검증
  3.  
  4.  
  5.  
  6. 테스트 코드 추가
반응형

 


 

@Valid 와 BindingResult (또는 Errors)

  • BindingResult 는 항상 @Valid 바로 다음 인자로 사용해야 함 (스프링 MVC)
  • @NotNull, @NotEmpty, @Min, @Max ... 사용해서 입력값 바인딩 할때 에러 확인이 가능하다

도메인 Validator 만들기

  • Validator 인터페이스 없이 만들어도 상관없다.

    @Component  
    public class EventValidator {
    
    public void validate(EventDto eventDto, Errors errors) {  
          if (eventDto.getBasePrice() > eventDto.getMaxPrice() && eventDto.getMaxPrice() != 0) {  
              errors.rejectValue("basePrice","wrongValue", "BasePrice is wrong");  
              errors.rejectValue("maxPrice","wrongValue", "MaxPrice is wrong");  
          } // errors 에다가 rejectValue 로 에러메세지를 넣어주는것 뿐이다. 간단함
    
          LocalDateTime endEventDateTime = eventDto.getEndEventDateTime();
          LocalDateTime closeEnrollmentDateTime = eventDto.getCloseEnrollmentDateTime();
          LocalDateTime beginEventDateTime = eventDto.getBeginEventDateTime();
    
          if (endEventDateTime.isBefore(beginEventDateTime) ||
                  endEventDateTime.isBefore(closeEnrollmentDateTime) ||
                  endEventDateTime.isBefore(eventDto.getBeginEnrollmentDateTime())) {
              errors.rejectValue("endEventDateTime", "wrongValue", "endEventDataTime is wrong");
          }
    
          // TODO beginEventDataTime
          if (beginEventDateTime.isBefore(closeEnrollmentDateTime) ||
                  beginEventDateTime.isBefore(eventDto.getBeginEnrollmentDateTime())) {
              errors.rejectValue("beginEventDateTime", "wrongValue", "beginEventDateTime is wrong");
          }
    
          // TODO CloseEnrollmentDateTime
          if (closeEnrollmentDateTime.isBefore(eventDto.getBeginEnrollmentDateTime())) {
              errors.rejectValue("closeEnrollmentDateTime","wrongValue", "closeEnrollmentDateTime is wrong" );
          }
    }  
    }

Controller 에서 검증

@Controller  
@RequestMapping(value = "/api/events", produces = MediaTypes.HAL\_JSON\_VALUE)  
public class EventController {

private final EventRepository eventRepository;

private final ModelMapper modelMapper;

//validator를 생성자를 통해 빈을 주입받고  
private final EventValidator eventValidator;

//생성자가 하나만있고, 받아올 타입이 빈으로 등록되어있으면 autowired 생략 가능  
public EventController(EventRepository eventRepository, ModelMapper modelMapper, EventValidator eventValidator) {  
      this.eventRepository = eventRepository;  
      this.modelMapper = modelMapper;  
      this.eventValidator = eventValidator;  
}

//   @Valid 를 붙여주면, EventDto의 Entity에 붙어있는 애노테이션을 기반으로 검증을 해준다
//   에러 발생시 Errors에다가 에러의 정보를 담아준다. 
    @PostMapping  
    public ResponseEntity createEvent(@RequestBody @Valid EventDto eventDto, Errors errors) {  
    //@Valid 오류가 난다면, 의존성 추가 : spring-boot-starter-validation 을 해준다.  
    if (errors.hasErrors()) {
      return ResponseEntity.badRequest().build();
    }

    //validator로 검증 -> errors에 error를 넣어준다. 에러 발생시 -> badRequest 발생!  
    eventValidator.validate(eventDto, errors);  
    if (errors.hasErrors()) {
      return ResponseEntity.badRequest().build();    
    }

    Event event = modelMapper.map(eventDto, Event.class);

    Event newEvent = this.eventRepository.save(event);  
    //link를 생성할땐,  
    //HATEOAS가 제공하는 linkTo(), methodOn()을 사용 , 지금은 클래스레벨에 RequestMapping이 걸렸기때문에 methodOn 사용 X  
    URI createUri = linkTo(EventController.class).slash(newEvent.getId()).toUri();  
    return ResponseEntity.created(createUri).body(event); //201응답을 Uri에 담아서 리턴시킨다.  
    }    
}

 

테스트 설명 용 애노테이션 만들기

  • @Target , @Retention
 @Target(value = ElementType.METHOD)
 @Retention(RetentionPolicy.SOURCE)
 public @interface TestDescription {
     String value();
 }

생성하고 각 테스트 마다 설명을 적어주면 된다. 그러면 테스트를 실행할때, 메소드 이름말고

내가 @TestDescription에 넣어준 문자열이 출력이 되는데.. 난 안됨

 

 

테스트 코드 추가

  • 끝나는 시간이 시작 시간보다 빠르게 값을 넣어주고, validator가 badRequest를 잘 보내는지 확인!
@Test  
@TestDescription("입력 값이 잘못된 경우에 에러가 발생하는 테스트")  
public void createEvent_Bad_Request_Wrong_Input() throws Exception {  
    EventDto eventDto = EventDto.builder()  
        .name("Spring")  
        .description("REST API Development with Spring")  
        .beginEnrollmentDateTime(LocalDateTime.of(2020, 9, 8, 2, 45)) //시작 날짜가 끝나는 날짜보다 빠름!  
        .closeEnrollmentDateTime(LocalDateTime.of(2020, 9, 7, 2, 45))  
        .beginEventDateTime(LocalDateTime.of(2020, 9, 10, 2, 45))  
        .endEventDateTime(LocalDateTime.of(2020, 9, 9, 2, 45))  
        .basePrice(10000) //maxPrice 보다 큼  
        .maxPrice(200)  
        .limitOfEnrollment(100)  
        .location("Daejoen")  
        .build();

  mockMvc.perform(post("/api/events")
                  .contentType(MediaTypes.HAL_JSON_VALUE)
                  .content(objectMapper.writeValueAsString(eventDto))
                  )
          .andDo(print())
          .andExpect(status().isBadRequest())
          ;
}
반응형
저작자표시 (새창열림)
  1. 도메인 Validator 만들기
  2. Controller 에서 검증
  3.  
  4.  
  5.  
  6. 테스트 코드 추가
'💐 Spring/Spring REST API' 카테고리의 다른 글
  • 7) [test] @JUnitParams 테스트 코드 리팩토링 - 스프링 REST API
  • 6) [test] Bad_Request 응답 본문 만들기 - 스프링 REST API
  • 4) [test] 입력값 제한하기 (Bad_Request 발생) - 스프링 REST API
  • 3) [test] 입력값 제한하기 (무시하는 방법) - 스프링 REST API
iseunghan
iseunghan
꾸준하게 열심히..
iseunghan
iseunghan

공지사항

  • 어제보다 나은 오늘이 되기 위해 🔥
  • 분류 전체보기 (262)
    • 💐 Spring (14)
      • 개념 및 이해 (2)
      • Spring 핵심 기술 (24)
      • Spring REST API (8)
      • Spring MVC, DB 접근 기술 (7)
      • Spring Security (23)
      • Spring in Action (1)
    • 🌻 JAVA (84)
      • 자바 ORM 표준 JPA 프로그래밍 (20)
      • 알고리즘, 자료구조 (13)
      • 디자인 패턴 (7)
      • 정리정리정리 (43)
      • JUnit (1)
    • 🔖 Snippets (3)
      • Javascript (3)
    • ⚙️ Devops (22)
      • ⛏ Git (11)
      • 🐳 Docker (6)
      • 🐧 Linux (3)
      • 🌈 Jenkins (1)
      • 📬 Kafka (1)
    • 💬 ETC.. (4)
      • 💻 macOS (2)
    • 🌧️ ORM (2)
      • JPA (2)
    • 🐍 Python (3)
    • 📚 Databases (15)
      • 오라클로 배우는 데이터베이스 개론과 실습(2판) (3)
      • RealMySQL 8.0 (8)
    • 🔥 Computer Science (5)
      • 📡 네트워크 (5)
    • 🏷️ 협업 (1)
    • 📜 코딩테스트 (38)
      • BAEKJOON\수학 1, 수학 2 (8)
      • BAEKJOON\재귀 (5)
      • BAEKJOON\브루트 포스 (3)
      • BAEKJOON\정렬 (1)
      • BAEKJOON\백트래킹 (5)
      • BAEKJOON\BFS, DFS (6)
      • BAEKJOON\이분탐색 (1)
      • BAEKJOON\다이나믹 프로그래밍 (9)
      • BAEKJOON\그리디 알고리즘 (0)
    • ✨ ISEUNGHAN (1)

인기 글

전체
오늘
어제
반응형
hELLO · Designed By 정상우.
iseunghan
5) [test] 입력값 제한하기 (비즈니스 로직으로 검사) - 스프링 REST API
상단으로

티스토리툴바

개인정보

  • 티스토리 홈
  • 포럼
  • 로그인

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.