RestApi 만들기 - 이벤트 수정 API구현 (11)

반응형
반응형

이번에는 강의를 듣기전에 먼저 작성하기로 해보자.

이벤트 수정의 경우는
1. 수정이 정상적으로 실행이 되었을때 : 200
2. 수정이 잘못된 경우
       - 비어있는 객체가 들어있을 경우.
       - 잘못된 객체가 들어올 경우..
       - 권한이 없는 사람이 접근했을 경우
       - 페이지가 존재하지 않는 경우
이렇게 들 수 있는데... 솔직히 2-3은 지금당장은 하지 못할 것 같다.
왜냐하면 유저를 고려하지 않았기 때문이다.
테스트 코드를 작성해보자.

@Test
  void update_event() throws Exception {
    Delivery delivery = generateEvent(100);
    DeliveryDto deliveryDto = modelMapper.map(delivery, DeliveryDto.class);
    deliveryDto.setItem("book");
    deliveryDto.setUser("klom2");
    deliveryDto.setItemPrice(1000);
    deliveryDto.setDeliveryTime(LocalDateTime.now());
    deliveryDto.setDeliveryEndTime(LocalDateTime.now().plusDays(10));
    this.mockMvc.perform(put("/api/delivery")
        .contentType(MediaType.APPLICATION_JSON)
        .content(objectMapper.writeValueAsString(deliveryDto)))
        .andDo(print())
        .andExpect(status().isOk())
        .andExpect(jsonPath("id").exists())
        .andExpect(jsonPath("user").value("klom2"))
        .andExpect(jsonPath("_link.self").exists())
        .andExpect(jsonPath("_link.profile").exists());
  }

정상적인 경우 테스트에 성공하는 컨트롤러를 만들어보자.

@PutMapping("/{id}")
public ResponseEntity<?> updateEvent(@PathVariable Integer id) {
  return ResponseEntity.ok().build();
}

이렇게 만들면 될까?
하지만 이렇게 만들면... id를 입력하지 않기 때문에 에러가 발생한다.
따라서..

 @PutMapping("/{id}")
  public ResponseEntity<?> updateEvent(@PathVariable Integer id) {
    Optional<Delivery> optionalDelivery = deliveryRepository.findById(id);
    Delivery delivery = optionalDelivery.get();
    EntityModel<Delivery> entityModel = DeliveryModel.modelOf(delivery);
    return ResponseEntity.ok(entityModel);
  }

이렇게 수정했다.
하지만 이렇게 만드니 새로운 문제가 발생했다.

그래서 이렇게 수정했다.

@PutMapping("/{id}")
public ResponseEntity<?> updateEvent(@PathVariable Integer id,
      @RequestBody @Valid DeliveryDto deliveryDto,Errors errors) {
    Optional<Delivery> optionalDelivery = deliveryRepository.findById(id);
    Delivery delivery = optionalDelivery.get();
    Delivery map = modelMapper.map(deliveryDto, Delivery.class);
    Delivery newDelivery = deliveryRepository.save(map);
    EntityModel<Delivery> entityModel = DeliveryModel.modelOf(newDelivery);
    return ResponseEntity.ok(entityModel);
}

이제 프로파일을 추가해보면...

테스트가 성공했다.
이제 다음 미션
수정이 잘못되었을 경우를 생각해보자.
비어있는 값일 경우에는 

if (errors.hasErrors()) {
   return errorResource(errors);
}

이것을 추가해주면 되었다.
값이 잘못된 경우에는

deliveryValidator.validate(deliveryDto, errors);
  if (errors.hasErrors()) {
    return errorResource(errors);
}

이걸 추가하면 되었다.!
최종적으로 

@PutMapping("/{id}")
  public ResponseEntity<?> updateEvent(@PathVariable Integer id,
      @RequestBody @Valid DeliveryDto deliveryDto,
      Errors errors) {
    Optional<Delivery> optionalDelivery = deliveryRepository.findById(id);

    if (errors.hasErrors()) {
      return errorResource(errors);
    }

    deliveryValidator.validate(deliveryDto, errors);
    if (errors.hasErrors()) {
      return errorResource(errors);
    }
    Delivery delivery = optionalDelivery.get();
    Delivery map = modelMapper.map(deliveryDto, Delivery.class);
    Delivery newDelivery = deliveryRepository.save(map);
    EntityModel<Delivery> entityModel = DeliveryModel.modelOf(newDelivery);
    entityModel
        .add(Link.of("http://localhost:8080/docs/index.html#update-event").withRel("profile"));
    return ResponseEntity.ok(entityModel);
  }

하 근데.. 너무 더럽긴 더럽다...ㅜㅜ
이따 리펙토링을 하자.
이제 doc으로 만들고 마치자..

@Test
  void update_event() throws Exception {
    Delivery delivery = generateEvent(100);
    DeliveryDto deliveryDto = modelMapper.map(delivery, DeliveryDto.class);
    deliveryDto.setItem("book");
    deliveryDto.setUser("klom2");
    deliveryDto.setItemPrice(1000);
    deliveryDto.setDeliveryTime(LocalDateTime.now());
    deliveryDto.setDeliveryEndTime(LocalDateTime.now().plusDays(10));
    this.mockMvc.perform(put("/api/delivery/{id}", delivery.getId())
        .contentType(MediaType.APPLICATION_JSON)
        .content(objectMapper.writeValueAsString(deliveryDto)))
        .andDo(print())
        .andExpect(status().isOk())
        .andExpect(jsonPath("id").exists())
        .andExpect(jsonPath("user").value("klom2"))
        .andExpect(jsonPath("_links.self").exists())
        .andExpect(jsonPath("_links.profile").exists())
        .andDo(document("update-event",
            links(linkWithRel("query-events").description("이벤트 생성페이지로"),
                linkWithRel("update-events").description("이벤트 수정페이지로"),
                linkWithRel("self").description("해당 이벤트로 이동페이지로"),
                linkWithRel("profile").description("해당 이벤트로 이동페이지로")),
            requestHeaders(headerWithName(HttpHeaders.CONTENT_TYPE).description("현재 contentType"),
                headerWithName(HttpHeaders.CONTENT_LENGTH).description("content 길이")),
            requestFields(fieldWithPath("item").description("상품명"),
                fieldWithPath("user").description("판매자"),
                fieldWithPath("deliveryTime").description("판매일"),
                fieldWithPath("deliveryEndTime").description("도착일"),
                fieldWithPath("itemPrice").description("상품가격")),

             responseHeaders(headerWithName(HttpHeaders.CONTENT_TYPE).description("현재 사용하고 있는 contentType")),
            responseFields(fieldWithPath("id").description("this item id"),
                            fieldWithPath("item").description("바꿀 상품명"),
                            fieldWithPath("user").description("바꿀 유저이름"),
                            fieldWithPath("deliveryTime").description("출발 시간"),
                            fieldWithPath("deliveryEndTime").description("도착 시간"),
                            fieldWithPath("status").description("현재 상품 상태"),
                            fieldWithPath("itemPrice").description("상품 가격"),
                            fieldWithPath("deliveryCost").description("배송비"),
                            fieldWithPath("_links.query-events.href").description("목록페이지로"),
                            fieldWithPath("_links.update-events.href").description("수정페이지로"),
                            fieldWithPath("_links.self.href").description("현재페이지로"),
                            fieldWithPath("_links.profile.href").description("현재 링크로 이동"))));
  }

어마어마하군..

중복된 부분과 쓸모없는 부분이 조금 보인다.
이제 리펙토링을 해야된다.
이거는 올리지 않을 예정...
그리고 나서 유저도 추가해주면 resapi끝!

반응형

댓글

Designed by JB FACTORY