RestApi ๋งŒ๋“ค๊ธฐ - ์ž…๋ ฅ๊ฐ’ ์ œํ•œํ•˜๊ธฐ + ์ž…๋ ฅ๊ฐ’ ์ด์™ธ์˜ ์—๋Ÿฌ ๋ฐœ์ƒ (3)

๋ฐ˜์‘ํ˜•

API๋ฅผ ๋งŒ๋“ค๋‹ค๋ณด๋ฉด,
์ž…๋ ฅ๊ฐ’์„ ์ œํ•œํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.
์˜ˆ๋ฅผ๋“ค๋ฉด,

public class Delivery {
    private int id;
    private String item;
    private String user;
    private LocalDateTime deliveryTime;
    private LocalDateTime deliveryEndTime;
    private DeliveryStatus status;
    private Integer itemPrice;
    private Integer deliveryCost;
}

์ด๋Ÿฐ ๊ฐ์ฒด๊ฐ€ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ด…์‹œ๋‹ค.
๊ทธ๋Ÿฐ๋ฐ, id๊ฐ™์€ ๊ฒฝ์šฐ jpa์—์„œ ๋ฒˆํ˜ธ๋ฅผ ์ •ํ•ด์ฃผ๊ณ ,
deliveryStatus๋Š”  ํ˜„์žฌ ๋ฐฐ๋‹ฌ์˜ ์ง„ํ–‰์„ ๋ณด๊ณ  ๊ฒฐ์ • ๋˜๊ณ ,
deliveryCost๋Š” itemPrice์˜ ๊ฐ’์„ ๋ณด๊ณ  ๊ฒฐ์ •ํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ณธ๋‹ค๋ฉด,

๋‘ ๊ฐ’์€ ์ž…๋ ฅ์„ ๋ฐ›์•„์„œ๋Š” ์•ˆ๋˜๋Š” ๊ฐ’๋“ค์ž…๋‹ˆ๋‹ค.
์™œ๋ƒํ•˜๋ฉด ์™ธ๋ถ€์—์„œ ๊ทธ ๊ฐ’๋“ค์„ ๊ฒฐ์ •ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด๋ด…์‹œ๋‹ค.

    @Test
        void create_Delivery() throws Exception {
            Delivery delivery = Delivery.builder()
                    .id(100)
                    .item("book")
                    .user("klom")
                    .build();
            Mockito.when(deliveryRepository.save(delivery)).thenReturn(delivery);
            mockMvc.perform(post("/api/delivery/")
                        .accept(MediaTypes.HAL_JSON_VALUE)
                        .contentType(MediaType.APPLICATION_JSON_VALUE)
                        .content(objectMapper.writeValueAsString(delivery))
                    )
                   .andDo(print())
                   .andExpect(status().isCreated())
                   .andExpect(jsonPath("id").value(Matchers.not(100)))
                   .andExpect(jsonPath("status").value(DeliveryStatus.READY))
                   .andExpect(jsonPath("deliveryCost").value(5000))
            ;
        }

id๊ฐ’์ด 100์ž…๋‹ˆ๋‹ค.
์ €ํฌ๋Š” id๊ฐ’์€ ์ž๋™์œผ๋กœ ์ฆ๊ฐ€๋˜๊ธฐ ์›ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์œ„ ์ฝ”๋“œ๋Š” 201๊ฐ€ ๋‚˜์™€์•ผ ๋ฉ๋‹ˆ๋‹ค.
ํ•˜์ง€๋งŒ 
๊ฒฐ๊ณผ๋Š” ํ…Œ์ŠคํŠธ ์‹คํŒจ์ž…๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ๋ ๊นŒ์š”?
๋ฐฉ๋ฒ•์€ ์—ฌ๋Ÿฌ๊ฐ€์ง€ ์ž…๋‹ˆ๋‹ค.

์ฒซ ๋ฒˆ์งธ ๋ฐฉ๋ฒ•์€ 
@JsonIgnore์–ด๋…ธํ…Œ์ด์…˜์„ ๋ถ™์ด๋ฉด ํ•ด๊ฒฐ๋˜๋Š” ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค.

public class Delivery {
    @Id
    @GeneratedValue
    private int id;
    private String item;
    private String user;
    private LocalDateTime deliveryTime;
    private LocalDateTime deliveryEndTime;
    @JsonIgnore
    private DeliveryStatus status;
    private Integer itemPrice;
    @JsonIgnore
    private Integer deliveryCost;
}


id๋Š” null์ด ๋ฐœ์ƒํ•ด์„œ ์ผ๋‹จ ๋ถ™์ด์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค;;
์ด๊ฒƒ์„ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ์ด๋”ฐ ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋ฉด

Body = {"id":100,"item":"book","user":"klom","deliveryTime":null,"deliveryEndTime":null,"itemPrice":null}


 @JsonIgnore์ด ๋ถ™์–ด์žˆ๋Š” ๊ณณ์€ json์œผ๋กœ ๋งŒ๋“ค์–ด์ง€์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๊ทธ๋ ‡๋‹ค๋ฉด json๋„ ์œ ์ง€ํ•˜๋ฉด์„œ ์—๋Ÿฌ๋ฅผ ์„ฑ๊ณตํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ์—†์„๊นŒ์š”?
dto๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

dto๋Š” api๋ฅผ ์œ„ํ•ด ๋งŒ๋“ค์–ด์ง€๋Š” ๊ฐ์ฒด๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

@NoArgsConstructor
@AllArgsConstructor
@Data
@Builder
public class DeliveryDto {
    private String item;
    private String user;
    private LocalDateTime deliveryTime;
    private LocalDateTime deliveryEndTime;
    private Integer itemPrice;
}

์ด๋ ‡๊ฒŒ ๋งŒ๋“ค๊ตฌ,

์ด์ œ ์ž…๋ ฅ์„ deliveyDto๋กœ ๋ฐ›๊ฒŒ ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.
๊ทผ๋ฐ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.

dto๋กœ ๋ฐ›๊ธฐ ๋•Œ๋ฌธ์— ์ปดํŒŒ์ผ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.
์ด๋Ÿด๋•Œ๋Š” ์–ด๋–ป๊ฒŒ ํ•ด์•ผ๋ ๊นŒ์š”?

์—ฌ๊ธฐ์—๋„ ๋ช‡ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.

์ฒซ ๋ฒˆ์งธ ๋ฐฉ๋ฒ• builder์„ ์ด์šฉํ•ด์„œ ๊ฐ’์„ ๋ฐ”์ธ๋”ฉํ•œ๋‹ค.

Delivery deliver = Delivery.builder()
                .item(deliveryDto.getItem())
                .user(deliveryDto.getUser())
                .build();

์ด๋ ‡๊ฒŒ ๊ฐ’์„ DeliveryDto์—์„œ delivery๋กœ ๋ณ€๊ฒฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
๋ฌผ๋ก  ํ…Œ์ŠคํŠธ๋Š” ์‹คํŒจ์ž…๋‹ˆ๋‹ค. ์ถ”ํ›„์— ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

๋‘ ๋ฒˆ์งธ ๋ฐฉ๋ฒ•์€ Modelmapper์„ ์ด์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

Modelmapper๋Š” ์„œ๋กœ ๋‹ค๋ฅธ ๊ฐ์ฒด๋ฅผ ๋ฐ”์ธ๋”ฉํ•ด์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค.
์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ์Šคํ”„๋งioc์—์„œ ๊ด€๋ฆฌํ•ด์ฃผ์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์ง์ ‘ ๋นˆ์œผ๋กœ ๋“ฑ๋กํ•ด์ค˜์•ผํ•ฉ๋‹ˆ๋‹ค.
์•„๋‹ˆ๋ฉด ๊ทธ๋ƒฅ ์“ฐ๋˜๊ฐ€.

๊ทธ๋Ÿฌ๋ฉด

Delivery deliver = modelMapper.map(deliveryDto, Delivery.class);

๋‹จ ํ•œ์ค„๋กœ ์™„์„ฑ์„ ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๋ฆฌํ”Œ๋ ‰์…˜ ๊ธฐ์ˆ ์„ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ข€ ๊ทธ๋ ‡๋‹ค ํ•˜๋Š” ๋ถ„๋“ค์€ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๊ฒƒ์„ ์ถ”์ฒœ๋“œ๋ฆฝ๋‹ˆ๋‹ค. ๊ทธ๋ƒฅ ๋นŒ๋” ์“ฐ์„ธ์š”.
์ž๋ฐ” ๋ฒ„์ „์ด ์˜ฌ๋ผ๊ฐ€๋ฉด์„œ ๋ฆฌํ”Œ๋ ‰์…˜ ๊ธฐ์ˆ ๋„ ๊ทธ๋ฆฌ ๋А๋ฆฌ์ง€๋Š” ์•Š๋Š”๋‹ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

์ด์ œ 

์ด ์˜ค๋ฅ˜๋ฅผ ํ•ด๊ฒฐํ•ด๋ด…์‹œ๋‹ค.

ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ๋‹ค์‹œ ๋ด…์‹œ๋‹ค.

๊ฐ€์žฅ ํฐ ๋ฌธ์ œ๋Š”

Mockito.when(deliveryRepository.save(delivery)).thenReturn(delivery);

๋ฐ”๋กœ ์ด ๋…€์„์ž…๋‹ˆ๋‹ค.
์ด๊ฒƒ์ด ๋ฌธ์ œ์ธ ์ด์œ ๋Š” 
์ปจํŠธ๋กค๋Ÿฌ์—์„œ๋Š” deliveryDto๋ฅผ ๋ฐ›๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๊ฒƒ์„ delivery๋กœ ๋ฐ”๊พธ๋Š” ์ž‘์—…์„ ๊ฐ€์กŒ์Šต๋‹ˆ๋‹ค.
๊ทผ๋ฐ ์ƒ๊ฐํ•ด์•ผ ๋ ๊ฒƒ์ด ์ด ๋ฐ”๊พผ delivery์™€ ํ…Œ์ŠคํŠธ์˜ delivery๋Š” ๊ฐ™์€ ๊ฐ์ฒด์ผ๊นŒ์š”?

์œ„ ์ฝ”๋“œ๋Š” ํ…Œ์ŠคํŠธ์˜ delivery๋ฅผ ๋งํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
์ฆ‰, ๊ฐ™์€ ์ฃผ์†Œ๊ฐ’์ด ๋“ค์–ด๊ฐ€์•ผ ์œ„ ์ฝ”๋“œ๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ๋™์ž‘ํ•œ๋‹ค๋Š” ๋œป์ž…๋‹ˆ๋‹ค.

์ปจํŠธ๋กค๋Ÿฌ์˜ delivery : restapiset.Delivery@3b
ํ…Œ์ŠคํŠธ์˜ delivery : restapiset.Delivery@9f


๊ทธ๋Ÿฌ๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ๋ ๊นŒ์š”?

์—ฌ๊ธฐ์—๋„ ์—ฌ๋Ÿฌ ๊ฐ€์ง€๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค.

์ฒซ ๋ฒˆ์งธ ๋ฐฉ๋ฒ•์€ ๋ชจ๋“  delivey๊ฐ์ฒด๋ฅผ saveํ•œ๋‹ค๋ฉด delivery๋ฅผ ๋ฆฌํ„ด์‹œํ‚ค๋ฉด ๋ฉ๋‹ˆ๋‹ค.

import static org.mockito.ArgumentMatchers.any;

Mockito.when(deliveryRepository.save(any(Delivery.class))).thenReturn(delivery);

์ƒ๊ฐํ•ด๋ ๊ฒƒ์ด ๋ชจ๋“  delivery๊ฐ์ฒด๋ฅผ ํ—ˆ์šฉํ• ๊นŒ์ž…๋‹ˆ๋‹ค.
๊ณผ์—ฐ ์ด๋ ‡๊ฒŒ ํ•ด๋„ ์ข‹์„๊นŒ?

๋‘ ๋ฒˆ์งธ ๋ฐฉ๋ฒ•์€ ์Šฌ๋ผ์ด์‹ฑ ํ…Œ์ŠคํŠธ์˜ ์œ„์น˜๋ฅผ ์Šคํ”„๋ง๋ถ€ํŠธ ํ…Œ์ŠคํŠธ๋กœ ์ˆ˜์ •ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
ํ•˜์ง€๋งŒ ๋ฌธ์ œ๋Š” mockMvc๋ฅผ ์‚ฌ์šฉ์ด ๋ถˆ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

@SpringBootTest
@AutoConfigureMockMvc
class DeliveryTest {

์ด๊ฑธ ๋ถ™์ด๋Š” ์ˆœ๊ฐ„ mockMvc๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

์ด๋ ‡๊ฒŒ ๋˜๋ฉด ๋” ์ด์ƒ ๋ชฉ๋นˆ์€ ํ•„์š”์—†์Šต๋‹ˆ๋‹ค.
์™œ๋ƒํ•˜๋ฉด ํ…Œ์ŠคํŠธ์—์„œ saveํ•  ์ด์œ ๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๋งˆ์ง€๋ง‰์œผ๋กœ delivery๋ฅผ ์ˆ˜์ •ํ•ฉ์‹œ๋‹ค.

public class Delivery {
    @Id
    @GeneratedValue
    private int id;
    private String item;
    private String user;
    private LocalDateTime deliveryTime;
    private LocalDateTime deliveryEndTime;
    private DeliveryStatus status = DeliveryStatus.READY;
    private Integer itemPrice;
    private Integer deliveryCost = 5000;
}

์ดˆ๊ธฐ๊ฐ’์„ ์ด๋ ‡๊ฒŒ ์„ธํŒ…ํ•ด ๋‘๊ณ ,

spring.jackson.deserialization.fail-on-unknown-properties=true


ํ…Œ์ŠคํŠธ๋ฅผ ํ•˜๊ฒŒ ๋˜๋ฉด ์ž˜๋ชป๋œ ๊ฐ’์ด ๋“ค์–ด์˜ค๋ฉด 400์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

 

 

 

 

 

 

 

๋Œ“๊ธ€

Designed by JB FACTORY