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