๐Ÿช kakaotech campus

์นดํ…Œ์ผ | [STEP2 clone coding] 2์ฃผ์ฐจ ๊ณผ์ œ - (2)

c0zi 2023. 7. 7. 21:12

2. Mock API Controller ๊ตฌํ˜„


02) ๊ฐ€์งœ ๋ฐ์ดํ„ฐ๋ฅผ ์„ค๊ณ„ํ•˜์—ฌ ์‘๋‹ตํ•˜๋Š” ์Šคํ”„๋ง๋ถ€ํŠธ ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ์ž‘์„ฑํ•˜๊ณ  ์†Œ์Šค์ฝ”๋“œ๋ฅผ ์—…๋กœ๋“œํ•˜์‹œ์˜ค.

 

์นดํ…Œ์ผ์„ ์ง„ํ–‰ํ•˜๋ฉด์„œ controller์™€ DTO ๋“ฑ์„ ๋ฐฐ์šฐ๊ธด ํ–ˆ์—ˆ์ง€๋งŒ, ์ •๋ง ํœ™ํœ™ ์ง€๋‚˜๊ฐ€๋Š” ์ •๋„๋กœ๋งŒ ๊ณต๋ถ€ํ–ˆ์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ณ ๋ ค์‚ฌํ•ญ๋“ค์„ ์–ด๋–ป๊ฒŒ ๊ตฌํ˜„ํ•˜๋Š”์ง€, ์–ด๋–ค ๋ฐฉ์‹์œผ๋กœ ๋กœ์ง์„ ์งœ์•ผ ํšจ์œจ์ ์ธ์ง€ ๋“ฑ์˜ ๋ฌธ์ œ๋Š” ์ œ์ณ๋‘๊ณ  ๊ธฐ์กด์˜ ์ฝ”๋“œ๋ฅผ ์ดํ•ดํ•˜๊ณ  ํ”Œ๋Ÿฌ์Šค๋กœ ํ•„์š”ํ•œ ๋ถ€๋ถ„๋งŒ ๊ตฌํ˜„ํ•˜๋Š” ์‹์œผ๋กœ ๊ณผ์ œ๋ฅผ ์ˆ˜ํ–‰ํ•ด๋ณด๋ ค๊ณ  ํ•œ๋‹ค.

 

Mock : ์‹ค์ œ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด ์‚ฌ์šฉํ•˜๊ธฐ์— ์‹œ๊ฐ„, ๋น„์šฉ ๋“ฑ์˜ Cost๊ฐ€ ๋†’๊ฑฐ๋‚˜ ํ˜น์€ ๊ฐ์ฒด ์„œ๋กœ๊ฐ„์˜ ์˜์กด์„ฑ์ด ๊ฐ•ํ•ด ๊ตฌํ˜„ํ•˜๊ธฐ ํž˜๋“ค ๊ฒฝ์šฐ ๊ฐ€์งœ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•
๊ฐ€์งœ ๋ฐ์ดํ„ฐ (dummy data) : ์œ ์šฉํ•œ ๋ฐ์ดํ„ฐ๊ฐ€ ํฌํ•จ๋˜์ง€ ์•Š์ง€๋งŒ ๊ณต๊ฐ„์„ ์˜ˆ๋น„ํ•ด๋‘์–ด ์‹ค์ œ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ช…๋ชฉ์ƒ ์กด์žฌํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋‹ค๋ฃจ๋Š” ์œ ์ˆœํ•œ ์ •๋ณด๋ฅผ ์˜๋ฏธ

 

๊ณผ์ œ์— ๋”ฐ๋ฅด๋ฉด ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ์ž‘์„ฑํ•ด์•ผ ํ•˜๋Š”๋ฐ, ๋งŽ์ด ๋“ค์–ด๋ณธ ์ด '์ปจํŠธ๋กค๋Ÿฌ'์˜ ์ •ํ™•ํ•œ ์ •์˜๊ฐ€ ๊ถ๊ธˆํ–ˆ๋‹ค.

 

Controller๋Š” ํ™”๋ฉด(View)๊ณผ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง(Model)๋ฅผ ์—ฐ๊ฒฐ์‹œํ‚ค๋Š” ๋‹ค๋ฆฌ ์—ญํ• ์ด๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ๋‹ค.

๋”์šฑ ์ง๊ด€์ ์œผ๋กœ ์„ค๋ช…ํ•˜์ž๋ฉด, ์ฃผ์†Œ๋ฅผ ์ž…๋ ฅ ๋ฐ›์•„ ์–ด๋””๋กœ ๊ฐˆ์ง€ ๋ถ„์„ํ•˜๊ณ  ๋งž๋Š” ๊ธธ๋กœ ์—ฐ๊ฒฐ์‹œ์ผœ์ฃผ๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.

 

@Controller ์–ด๋…ธํ…Œ์ด์…˜์„ ํ†ตํ•ด ํด๋ž˜์Šค์— ์ปจํŠธ๋กค๋Ÿฌ ์—ญํ• ์„ ๋ถ€์—ฌํ•œ๋‹ค. 

 

https://luanaeun.tistory.com/200

 

Spring) ์Šคํ”„๋ง Controller ๊ฐœ๋…๊ณผ ํŽ˜์ด์ง€ ์—ฐ๊ฒฐ(์ฃผ์†Œ๋งคํ•‘)

1. ์ปจํŠธ๋กค๋Ÿฌ๋ž€? ์Šคํ”„๋ง ํ”„๋ ˆ์ž„์›Œํฌ๋Š” MVCํŒจํ„ด์„ ์‚ฌ์šฉํ•˜๊ณ ์žˆ๊ณ , ์—ฌ๊ธฐ์„œ Controller๋Š” ํ™”๋ฉด(View)๊ณผ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง(Model)๋ฅผ ์—ฐ๊ฒฐ์‹œํ‚ค๋Š” ๋‹ค๋ฆฌ ์—ญํ• ์„ ํ•œ๋‹ค. ์‰ฝ๊ฒŒ ๋งํ•˜์ž๋ฉด ํ™”๋ฉด์—์„œ /aaa ๋กœ ๊ฐ€์ค˜~ ํ•˜๊ณ  ์š”์ฒญ

luanaeun.tistory.com

 

ApiUtils.java

package com.example.kakaoshop._core.utils;

import lombok.*;
import org.springframework.http.HttpStatus;

public class ApiUtils {

	public static <T> ApiResult<T> success(T response) {
		return new ApiResult<>(true, response, null);
	}
    
	public static ApiResult<?> error(String message, HttpStatus status) {
		return new ApiResult<>(false, null, new ApiError(message, status.value()));
	}
    
	@Getter @Setter @AllArgsConstructor
	public static class ApiResult<T> {
		private final boolean success;
		private final T response;
		private final ApiError error;
	}
    
	@Getter @Setter @AllArgsConstructor
	public static class ApiError {
		private final String message;
		private final int status;
	}
}

 

์œ„์˜ ์œ ํ‹ธ๋ฆฌํ‹ฐ ํด๋ž˜์Šค์—์„œ๋Š” ์„ฑ๊ณต ์—ฌ๋ถ€๋ฅผ Boolean ํ˜•ํƒœ๋กœ๋„ ์ค„ ์ˆ˜ ์žˆ์ง€๋งŒ http ์ƒํƒœ ์ฝ”๋“œ ํ˜•ํƒœ๋กœ๋„ ์ค„ ์ˆ˜ ์žˆ๋‹ค.

์ค‘์š”ํ•œ ๊ฒƒ์€ ์–ด๋–ค ๊ฒƒ์ด ํ”„๋ก ํŠธ์—์„œ ๋ฐ›์•˜์„ ๋•Œ ๋” ์ดํ•ดํ•˜๊ธฐ ์‰ฝ๊ฒŒ ์ง๊ด€์ ์œผ๋กœ ์„ค๊ณ„ ํ–ˆ๊ณ  ์ผ๊ด€์„ฑ์ด ์žˆ๋Š”์ง€๊ฐ€ ์ค‘์š”ํ•˜๋‹ค.

์ด ApiUtils.java ํด๋ž˜์Šค๋ฅผ ์ด์šฉํ•˜์—ฌ Api ์‘๋‹ต์„ ์ฒ˜๋ฆฌํ•  ๊ฒƒ์ด๋‹ค.

 


์ƒํ’ˆ ๋ชฉ๋ก ๋ณด๊ธฐ ๊ธฐ๋Šฅ Mock ๊ตฌํ˜„


JSON request body

{
    "success": true,
    "response": [
        {
            "id": 1,
            "productName": "๊ธฐ๋ณธ์— ์Šฌ๋ผ์ด๋”ฉ ์ง€ํผ๋ฐฑ ํฌ๋ฆฌ์Šค๋งˆ์Šค/ํ”Œ๋ผ์›Œ์—๋””์…˜ ์—๋””์…˜ ์™ธ ์ฃผ๋ฐฉ์šฉํ’ˆ ํŠน๊ฐ€์ „",
            "description": "",
            "image": "/images/1.jpg",
            "price": 1000
        },
        {
            "id": 2,
            "productName": "[ํ™ฉ๊ธˆ์•ฝ๋‹จ๋ฐค ๊ณจ๋“œ]2022๋…„์‚ฐ ํ–‡๋ฐค ์นผ์ง‘๋ฐค700g์™ธ/๊ตฐ๋ฐค์šฉ/์ƒ์œจ",
            "description": "",
            "image": "/images/2.jpg",
            "price": 2000
        },
        {
            "id": 3,
            "productName": "์‚ผ์„ฑ์ „์ž JBL JR310 ์™ธ ์–ด๋ฆฐ์ด์šฉ/์„ฑ์ธ์šฉ ํ—ค๋“œ์…‹ 3์ข…!",
            "description": "",
            "image": "/images/3.jpg",
            "price": 30000
        },
        {
            "id": 4,
            "productName": "๋ฐ”๋ฅธ ๋ˆ„๋ฃฝ์ง€๋ง› ๋ฐœํšจํšจ์†Œ 2๋ฐ•์Šค ์—ญ๊ฐ€์ˆ˜์น˜๋ณด์žฅ / ์™ธ 7์ข…",
            "description": "",
            "image": "/images/4.jpg",
            "price": 4000
        },
        {
            "id": 5,
            "productName": "[๋”์ฃผ] ์ปทํŒ…๋ง๋ž‘์žฅ์กฑ, ์ˆ๋‹ค๋ฆฌ 100g/300g ์™ธ ์ฃผ์ „๋ถ€๋ฆฌ ๋ชจ์Œ /์ค‘๋…์„ฑ ์ตœ๊ณ /๋งˆ๋ฅธ์•ˆ์ฃผ",
            "description": "",
            "image": "/images/5.jpg",
            "price": 5000
        },
        {
            "id": 6,
            "productName": "๊ตณ์ง€์•Š๋Š” ์•™๊ธˆ์ ˆํŽธ 1,050g 2ํŒฉ ์™ธ ์šฐ๋ฆฌ์Œ€๋–ก ๋ชจ์Œ์ „",
            "description": "",
            "image": "/images/6.jpg",
            "price": 15900
        },
        {
            "id": 7,
            "productName": "eoe ์ด๋„ˆ๋”œ๋ฆฌํ‹ฐ 30ํฌ, ์˜ค๋ Œ์ง€๋ง› ๊ณ  ์‹์ด์„ฌ์œ  ๋ณด์ถฉ์ œ",
            "description": "",
            "image": "/images/7.jpg",
            "price": 26800
        },
        {
            "id": 8,
            "productName": "์ œ๋‚˜๋ฒจ PDRN ํฌ๋ฆผ 2๊ฐœ. ํ”ผ๋ถ€๋ณด์Šต/์ง„์ • ์ผ€์–ด",
            "description": "",
            "image": "/images/8.jpg",
            "price": 25900
        },
        {
            "id": 9,
            "productName": "ํ”Œ๋ ˆ์ด์Šคํ…Œ์ด์…˜ VR2 ํ˜ธ๋ผ์ด์ฆŒ ๋ฒˆ๋“ค. ์ƒ์ƒํ•œ ๋ชฐ์ž…๊ฐ",
            "description": "",
            "image": "/images/9.jpg",
            "price": 797000
        }
    ],
    "error": null
}

 

1. ProductRespFindAllDTO

import lombok.Builder;
import lombok.Getter;
import lombok.Setter;

@Getter @Setter
public class ProductRespFindAllDTO {

    private int id;
    private String productName;
    private String description;
    private String image;
    private int price;

    @Builder
    public ProductRespFindAllDTO(int id, String productName, String description, String image, int price) {
        this.id = id;
        this.productName = productName;
        this.description = description;
        this.image = image;
        this.price = price;
    }
}

 

product ํŒจํ‚ค์ง€ ๋‚ด์˜ response ํŒจํ‚ค์ง€๋ฅผ ๋งŒ๋“ค์–ด DTO ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ ๋‹ค.

 

@Getter, @Setter ์–ด๋…ธํ…Œ์ด์…˜์„ ํ†ตํ•ด ์ž๋™์œผ๋กœ getter์™€ setter๊ฐ€ ์ƒ์„ฑ๋˜๋„๋ก ํ•˜๊ณ  Builder ์–ด๋…ธํ…Œ์ด์…˜์„ ํ†ตํ•ด ๋ฉค๋ฒ„ ํ•„๋“œ๋“ค์— ๋Œ€ํ•ด ๋นŒ๋”๋ฅผ ๋งŒ๋“ค์–ด์ค€๋‹ค.

 

CartRespFindAllDTO ํด๋ž˜์Šค๋Š” ์žฅ๋ฐ”๊ตฌ๋‹ˆ ์กฐํšŒ์— ๋Œ€ํ•œ ์‘๋‹ต ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๊ธฐ ์œ„ํ•œ DTO(Data Transfer Object)์ž…๋‹ˆ๋‹ค. ์ด DTO๋Š” @Getter์™€ @Setter ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ ์ž๋™์œผ๋กœ ํ•„๋“œ์˜ getter์™€ setter ๋ฉ”์„œ๋“œ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

์ฐธ๊ณ 
1. @Getter, @Setter
https://gocoder.tistory.com/2354
2. @Builder๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ 
https://pamyferret.tistory.com/67

 

2. ProductRestController

@RestController
public class ProductRestController {

    @GetMapping("/products")
    public ResponseEntity<?> findAll() {
        List<ProductRespFindAllDTO> responseDTO = new ArrayList<>();

        // ์ƒํ’ˆ ํ•˜๋‚˜์”ฉ ์ง‘์–ด๋„ฃ๊ธฐ
        responseDTO.add(new ProductRespFindAllDTO(
                1, "๊ธฐ๋ณธ์— ์Šฌ๋ผ์ด๋”ฉ ์ง€ํผ๋ฐฑ ํฌ๋ฆฌ์Šค๋งˆ์Šค/ํ”Œ๋ผ์›Œ์—๋””์…˜ ์—๋””์…˜ ์™ธ ์ฃผ๋ฐฉ์šฉํ’ˆ ํŠน๊ฐ€์ „", "", "/images/1.jpg", 1000
        ));
        responseDTO.add(new ProductRespFindAllDTO(
                2, "[ํ™ฉ๊ธˆ์•ฝ๋‹จ๋ฐค ๊ณจ๋“œ]2022๋…„์‚ฐ ํ–‡๋ฐค ์นผ์ง‘๋ฐค700g์™ธ/๊ตฐ๋ฐค์šฉ/์ƒ์œจ", "", "/images/2.jpg", 2000
        ));
        responseDTO.add(new ProductRespFindAllDTO(
                3, "์‚ผ์„ฑ์ „์ž JBL JR310 ์™ธ ์–ด๋ฆฐ์ด์šฉ/์„ฑ์ธ์šฉ ํ—ค๋“œ์…‹ 3์ข…!", "", "/images/3.jpg", 30000
        ));
        responseDTO.add(new ProductRespFindAllDTO(
                4, "๋ฐ”๋ฅธ ๋ˆ„๋ฃฝ์ง€๋ง› ๋ฐœํšจํšจ์†Œ 2๋ฐ•์Šค ์—ญ๊ฐ€์ˆ˜์น˜๋ณด์žฅ / ์™ธ 7์ข…", "", "/images/4.jpg", 4000
        ));
        responseDTO.add(new ProductRespFindAllDTO(
                5, "[๋”์ฃผ] ์ปทํŒ…๋ง๋ž‘์žฅ์กฑ, ์ˆ๋‹ค๋ฆฌ 100g/300g ์™ธ ์ฃผ์ „๋ถ€๋ฆฌ ๋ชจ์Œ /์ค‘๋…์„ฑ ์ตœ๊ณ /๋งˆ๋ฅธ์•ˆ์ฃผ", "", "/images/5.jpg", 5000
        ));
        responseDTO.add(new ProductRespFindAllDTO(
                6, "๊ตณ์ง€์•Š๋Š” ์•™๊ธˆ์ ˆํŽธ 1,050g 2ํŒฉ ์™ธ ์šฐ๋ฆฌ์Œ€๋–ก ๋ชจ์Œ์ „", "", "/images/6.jpg", 15900
        ));
        responseDTO.add(new ProductRespFindAllDTO(
                7, "eoe ์ด๋„ˆ๋”œ๋ฆฌํ‹ฐ 30ํฌ, ์˜ค๋ Œ์ง€๋ง› ๊ณ  ์‹์ด์„ฌ์œ  ๋ณด์ถฉ์ œ", "", "/images/7.jpg", 26800
        ));
        responseDTO.add(new ProductRespFindAllDTO(
                8, "์ œ๋‚˜๋ฒจ PDRN ํฌ๋ฆผ 2๊ฐœ. ํ”ผ๋ถ€๋ณด์Šต/์ง„์ • ์ผ€์–ด", "", "/images/8.jpg", 25900
        ));
        responseDTO.add(new ProductRespFindAllDTO(
                9, "ํ”Œ๋ ˆ์ด์Šคํ…Œ์ด์…˜ VR2 ํ˜ธ๋ผ์ด์ฆŒ ๋ฒˆ๋“ค. ์ƒ์ƒํ•œ ๋ชฐ์ž…๊ฐ", "", "/images/9.jpg", 797000
        ));


        return ResponseEntity.ok().body(ApiUtils.success(responseDTO));
    }
}

 

์ปจํŠธ๋กค๋Ÿฌ์— ํ•˜๋‚˜์”ฉ ์ง์ ‘ ๋„ฃ์–ด์„œ ๊ฐ€์งœ ์‘๋‹ต ๋ฐ์ดํ„ฐ๋ฅผ ๋งŒ๋“ ๋‹ค.

 

3. test

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;

@AutoConfigureMockMvc
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)
public class ProductRestControllerTest {
    @Autowired
    private MockMvc mvc;

    @Test
    // ์ „์ฒด ์ƒํ’ˆ ๋ชฉ๋ก ์กฐํšŒ
    public void findAll_test() throws Exception {
        // when
        ResultActions resultActions = mvc.perform(get("/products"));
        String responseBody = resultActions.andReturn().getResponse().getContentAsString();
        System.out.println("ํ…Œ์ŠคํŠธ : " + responseBody);

        // verify
        resultActions.andExpect(jsonPath("$.success").value("true"));
        resultActions.andExpect(jsonPath("$.response[0].id").value(1));
        resultActions.andExpect(jsonPath("$.response[0].productName").value("๊ธฐ๋ณธ์— ์Šฌ๋ผ์ด๋”ฉ ์ง€ํผ๋ฐฑ ํฌ๋ฆฌ์Šค๋งˆ์Šค/ํ”Œ๋ผ์›Œ์—๋””์…˜ ์—๋””์…˜ ์™ธ ์ฃผ๋ฐฉ์šฉํ’ˆ ํŠน๊ฐ€์ „"));
        resultActions.andExpect(jsonPath("$.response[0].description").value(""));
        resultActions.andExpect(jsonPath("$.response[0].image").value("/images/1.jpg"));
        resultActions.andExpect(jsonPath("$.response[0].price").value(1000));
        resultActions.andExpect(jsonPath("$.response[1].id").value(2));
        resultActions.andExpect(jsonPath("$.response[1].productName").value("[ํ™ฉ๊ธˆ์•ฝ ๋‹จ๋ฐค ๊ณจ๋“œ]2022๋…„์‚ฐ ํ–‡๋ฐค ์นผ์ง‘๋ฐค700g์™ธ/๊ตฐ๋ฐค์šฉ/์ƒ์œจ"));
        resultActions.andExpect(jsonPath("$.response[1].description").value(""));
        resultActions.andExpect(jsonPath("$.response[1].image").value("/images/2.jpg"));
        resultActions.andExpect(jsonPath("$.response[1].price").value(2000));
    }
}

 


์ƒํ’ˆ ์ƒ์„ธ ๋ณด๊ธฐ ๊ธฐ๋Šฅ Mock ๊ตฌํ˜„


JSON ์‘๋‹ต

 

1. ProductRespFindByIdDTO

import lombok.Builder;
import lombok.Getter;
import lombok.Setter;

import java.util.List;

@Getter @Setter
public class ProductRespFindByIdDTO {

    private int id;
    private String productName;
    private String description;
    private String image;
    private int price;
    private int starCount; // 0~5
    private List<ProductOptionDTO> options;

    @Builder
    public ProductRespFindByIdDTO(int id, String productName, String description, String image, int price, int starCount, List<ProductOptionDTO> options) {
        this.id = id;
        this.productName = productName;
        this.description = description;
        this.image = image;
        this.price = price;
        this.starCount = starCount;
        this.options = options;
    }
}

 

2. ProductOptionDTO

import lombok.Builder;
import lombok.Getter;
import lombok.Setter;

@Getter @Setter
public class ProductOptionDTO {

    private int id;
    private String optionName;
    private int price;

    @Builder
    public ProductOptionDTO(int id, String optionName, int price) {
        this.id = id;
        this.optionName = optionName;
        this.price = price;
    }
}

 

3. findById

@GetMapping("/products/{id}")
public ResponseEntity<?> findById(@PathVariable int id) {
    // ์ƒํ’ˆ์„ ๋‹ด์„ DTO ์ƒ์„ฑ
    ProductRespFindByIdDTO responseDTO = null;

    if(id == 1){
        List<ProductOptionDTO> optionDTOList = new ArrayList<>();
        optionDTOList.add(new ProductOptionDTO(1, "01. ์Šฌ๋ผ์ด๋”ฉ ์ง€ํผ๋ฐฑ ํฌ๋ฆฌ์Šค๋งˆ์Šค์—๋””์…˜ 4์ข…", 10000));
        optionDTOList.add(new ProductOptionDTO(2, "02. ์Šฌ๋ผ์ด๋”ฉ ์ง€ํผ๋ฐฑ ํ”Œ๋ผ์›Œ์—๋””์…˜ 5์ข…", 10900));
        optionDTOList.add(new ProductOptionDTO(3, "๊ณ ๋ฌด์žฅ๊ฐ‘ ๋ฒ ์ด์ง€ S(์†Œํ˜•) 6ํŒฉ", 9900));
        optionDTOList.add(new ProductOptionDTO(4, "๋ฝ‘์•„์“ฐ๋Š” ํ‚ค์นœํƒ€์˜ฌ 130๋งค 12ํŒฉ", 16900));
        optionDTOList.add(new ProductOptionDTO(4, "2๊ฒน ์‹๋นต์ˆ˜์„ธ๋ฏธ 6๋งค", 8900));
        responseDTO = new ProductRespFindByIdDTO(1, "๊ธฐ๋ณธ์— ์Šฌ๋ผ์ด๋”ฉ ์ง€ํผ๋ฐฑ ํฌ๋ฆฌ์Šค๋งˆ์Šค/ํ”Œ๋ผ์›Œ์—๋””์…˜ ์—๋””์…˜ ์™ธ ์ฃผ๋ฐฉ์šฉํ’ˆ ํŠน๊ฐ€์ „", "", "/images/1.jpg", 1000, 5, optionDTOList);

    }else if(id == 2){
        List<ProductOptionDTO> optionDTOList = new ArrayList<>();
        optionDTOList.add(new ProductOptionDTO(6, "22๋…„์‚ฐ ํ–‡๋‹จ๋ฐค 700g(ํ•œ์ •ํŒ๋งค)", 9900));
        optionDTOList.add(new ProductOptionDTO(7, "22๋…„์‚ฐ ํ–‡๋‹จ๋ฐค 1kg(ํ•œ์ •ํŒ๋งค)", 14500));
        optionDTOList.add(new ProductOptionDTO(8, "๋ฐค๊นŽ๊ธฐ+๋‹คํšŒ์šฉ ๊ตฌ์ดํŒ ์„ธํŠธ", 5500));
        responseDTO = new ProductRespFindByIdDTO(2, "[ํ™ฉ๊ธˆ์•ฝ๋‹จ๋ฐค ๊ณจ๋“œ]2022๋…„์‚ฐ ํ–‡๋ฐค ์นผ์ง‘๋ฐค700g์™ธ/๊ตฐ๋ฐค์šฉ/์ƒ์œจ", "", "/images/2.jpg", 2000, 5, optionDTOList);
    }else {
        return ResponseEntity.badRequest().body(ApiUtils.error("ํ•ด๋‹น ์ƒํ’ˆ์„ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค : " + id, HttpStatus.BAD_REQUEST));
    }

    return ResponseEntity.ok(ApiUtils.success(responseDTO));
}

 

3. Test

    @Test
// ๊ฐœ๋ณ„ ์ƒํ’ˆ ์ƒ์„ธ ์กฐํšŒ
    public void findById_test() throws Exception {
        // given
        int id = 1;

        // when
        ResultActions resultActions = mvc.perform(
                get("/products/" + id)
        );

        String responseBody = resultActions.andReturn().getResponse().getContentAsString();
        System.out.println("ํ…Œ์ŠคํŠธ : " + responseBody);

        // verify
        resultActions.andExpect(jsonPath("$.success").value("true"));
        resultActions.andExpect(jsonPath("$.response.id").value(1));
        resultActions.andExpect(jsonPath("$.response.productName").value("๊ธฐ๋ณธ์— ์Šฌ๋ผ์ด๋”ฉ ์ง€ํผ๋ฐฑ ํฌ๋ฆฌ์Šค๋งˆ์Šค/ํ”Œ๋ผ์›Œ์—๋””์…˜ ์—๋””์…˜ ์™ธ ์ฃผ๋ฐฉ์šฉํ’ˆ ํŠน๊ฐ€์ „"));
        resultActions.andExpect(jsonPath("$.response.description").value(""));
        resultActions.andExpect(jsonPath("$.response.image").value("/images/1.jpg"));
        resultActions.andExpect(jsonPath("$.response.price").value(1000));
        resultActions.andExpect(jsonPath("$.response.options[0].id").value(1));
        resultActions.andExpect(jsonPath("$.response.options[0].optionName").value("01. ์Šฌ๋ผ์ด๋”ฉ ์ง€ํผ๋ฐฑ ํฌ๋ฆฌ์Šค๋งˆ์Šค์—๋””์…˜ 4์ข…"));
        resultActions.andExpect(jsonPath("$.response.options[0].price").value(10000));
        resultActions.andExpect(jsonPath("$.response.options[1].id").value(2));
        resultActions.andExpect(jsonPath("$.response.options[1].optionName").value("02. ์Šฌ๋ผ์ด๋”ฉ ์ง€ํผ๋ฐฑ ํ”Œ๋ผ์›Œ์—๋””์…˜ 5์ข…"));
        resultActions.andExpect(jsonPath("$.response.options[1].price").value(10900));
    }

}

์žฅ๋ฐ”๊ตฌ๋‹ˆ ๋ชฉ๋ก ๋ณด๊ธฐ Mock ๊ตฌํ˜„


์‘๋‹ต JSON

 

1. CartRespFindAllDTO

import lombok.Builder;
import lombok.Getter;
import lombok.Setter;

import java.util.List;

@Getter @Setter
public class CartRespFindAllDTO {
    private List<ProductDTO> products;
    private int totalPrice;

    @Builder
    public CartRespFindAllDTO(List<ProductDTO> products, int totalPrice) {
        this.products = products;
        this.totalPrice = totalPrice;
    }
}

 

CartRespFindAllDTO ํด๋ž˜์Šค๋Š” ์žฅ๋ฐ”๊ตฌ๋‹ˆ ์กฐํšŒ์— ๋Œ€ํ•œ ์‘๋‹ต ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๊ธฐ ์œ„ํ•œ DTO(Data Transfer Object)์ด๋‹ค. @Getter์™€ @Setter ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ ์ž๋™์œผ๋กœ ํ•„๋“œ์˜ getter์™€ setter ๋ฉ”์„œ๋“œ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

 

๋˜ํ•œ @Builder ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜๋ฉด ์ƒ์„ฑ์ž ๋Œ€์‹ ์— ๋นŒ๋”๋ฅผ ํ†ตํ•ด ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ํ•„๋“œ ๊ฐ’์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๊ฐ์ฒด ์ƒ์„ฑ ์‹œ ํ•„์š”ํ•œ ํ•„๋“œ๋งŒ ์„ ํƒ์ ์œผ๋กœ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ๋‹ค.

 

2. ProductDTO

@Getter @Setter
public class ProductDTO {

	private int id;
	private String productName;
	private List<CartItemDTO> cartItems;
    
	@Builder
	public ProductDTO(int id, String productName, List<CartItemDTO> cartItems) {
		this.id = id;
		this.productName = productName;
		this.cartItems = cartItems;
	}
}

 

๋‹ค์Œ์œผ๋กœ, ProductDTO ๋‚ด๋ถ€์—๋Š” Product list์˜ ํ•„๋“œ์ธ id, productName, cartItems๊ฐ€ ํฌํ•จ๋œ๋‹ค.

 

3. CartItemDTO

import lombok.Builder;
import lombok.Getter;
import lombok.Setter;

@Getter @Setter
public class CartItemDTO {

    private int id;
    private ProductOptionDTO option;
    private int quantity;
    private int price;

    @Builder
    public CartItemDTO(int id, ProductOptionDTO option, int quantity, int price) {
        this.id = id;
        this.option = option;
        this.quantity = quantity;
        this.price = price;
    }
}

 

4. ProductOptionDTO

import lombok.Builder;
import lombok.Getter;
import lombok.Setter;

@Getter @Setter
public class ProductOptionDTO {

    private int id;
    private String optionName;
    private int price;

    @Builder
    public ProductOptionDTO(int id, String optionName, int price) {
        this.id = id;
        this.optionName = optionName;
        this.price = price;
    }
}

 

5. CartRestController

import com.example.kakaoshop._core.utils.ApiUtils;
import com.example.kakaoshop.cart.response.CartItemDTO;
import com.example.kakaoshop.cart.response.CartRespFindAllDTO;
import com.example.kakaoshop.cart.response.ProductOptionDTO;
import com.example.kakaoshop.cart.response.ProductDTO;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

@RestController
public class CartRestController {

    @GetMapping("/carts")
    public ResponseEntity<?> findAll() {
        // ์นดํŠธ ์•„์ดํ…œ ๋ฆฌ์ŠคํŠธ ๋งŒ๋“ค๊ธฐ
        List<CartItemDTO> cartItemDTOList = new ArrayList<>();

        // ์นดํŠธ ์•„์ดํ…œ ๋ฆฌ์ŠคํŠธ์— ๋‹ด๊ธฐ
        CartItemDTO cartItemDTO1 = CartItemDTO.builder()
                .id(4)
                .quantity(5)
                .price(50000)
                .build();
        cartItemDTO1.setOption(ProductOptionDTO.builder()
                                .id(1)
                                .optionName("01. ์Šฌ๋ผ์ด๋”ฉ ์ง€ํผ๋ฐฑ ํฌ๋ฆฌ์Šค๋งˆ์Šค์—๋””์…˜ 4์ข…")
                                .price(10000)
                                .build());
        cartItemDTOList.add(cartItemDTO1);

        CartItemDTO cartItemDTO2 = CartItemDTO.builder()
                .id(5)
                .quantity(5)
                .price(54500)
                .build();
        cartItemDTO2.setOption(ProductOptionDTO.builder()
                                .id(1)
                                .optionName("02. ์Šฌ๋ผ์ด๋”ฉ ์ง€ํผ๋ฐฑ ํฌ๋ฆฌ์Šค๋งˆ์Šค์—๋””์…˜ 5์ข…")
                                .price(10900)
                                .build());
        cartItemDTOList.add(cartItemDTO2);

        // productDTO ๋ฆฌ์ŠคํŠธ ๋งŒ๋“ค๊ธฐ
        List<ProductDTO> productDTOList = new ArrayList<>();

        // productDTO ๋ฆฌ์ŠคํŠธ์— ๋‹ด๊ธฐ
        productDTOList.add(
                ProductDTO.builder()
                        .id(1)
                        .productName("๊ธฐ๋ณธ์— ์Šฌ๋ผ์ด๋”ฉ ์ง€ํผ๋ฐฑ ํฌ๋ฆฌ์Šค๋งˆ์Šค/ํ”Œ๋ผ์›Œ์—๋””์…˜ ์—๋””์…˜ ์™ธ ์ฃผ๋ฐฉ์šฉํ’ˆ ํŠน๊ฐ€์ „")
                        .cartItems(cartItemDTOList)
                        .build()
        );

        CartRespFindAllDTO responseDTO = new CartRespFindAllDTO(productDTOList, 104500);

        return ResponseEntity.ok(ApiUtils.success(responseDTO));
    }
}

 

์‘๋‹ต JSON์— ๋งž์ถฐ ProductOptionDTO๊นŒ์ง€ ์ƒ์„ฑํ•œ ๋’ค Controller๋ฅผ ํ†ตํ•ด ๊ฐ€์งœ ๋ฐ์ดํ„ฐ๋ฅผ ์ž…๋ ฅํ•ด์ค€๋‹ค.

 

 

6. Test

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;


@AutoConfigureMockMvc
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)
public class CartRestControllerTest {
    @Autowired
    private MockMvc mvc;

    @Test
    @WithMockUser
    // ์ „์ฒด ์ƒํ’ˆ ๋ชฉ๋ก ์กฐํšŒ
    public void findAll_test() throws Exception {

        // when
        ResultActions resultActions = mvc.perform(
                get("/carts")
        );

        String responseBody = resultActions.andReturn().getResponse().getContentAsString();
        System.out.println("ํ…Œ์ŠคํŠธ : " + responseBody);

        // verify
        resultActions.andExpect(jsonPath("$.success").value("true"));
        resultActions.andExpect(jsonPath("$.response.totalPrice").value(104500));
        resultActions.andExpect(jsonPath("$.response.products[0].id").value(1));
        resultActions.andExpect(jsonPath("$.response.products[0].productName").value("๊ธฐ๋ณธ์— ์Šฌ๋ผ์ด๋”ฉ ์ง€ํผ๋ฐฑ ํฌ๋ฆฌ์Šค๋งˆ์Šค/ํ”Œ๋ผ์›Œ์—๋””์…˜ ์—๋””์…˜ ์™ธ ์ฃผ๋ฐฉ์šฉํ’ˆ ํŠน๊ฐ€์ „"));
        resultActions.andExpect(jsonPath("$.response.products[0].cartItems[0].id").value(4));
        resultActions.andExpect(jsonPath("$.response.products[0].cartItems[0].option.id").value(1));
        resultActions.andExpect(jsonPath("$.response.products[0].cartItems[0].option.optionName").value("01. ์Šฌ๋ผ์ด๋”ฉ ์ง€ํผ๋ฐฑ ํฌ๋ฆฌ์Šค๋งˆ์Šค์—๋””์…˜ 4์ข…"));
        resultActions.andExpect(jsonPath("$.response.products[0].cartItems[0].option.price").value(10000));
        resultActions.andExpect(jsonPath("$.response.products[0].cartItems[0].quantity").value(5));
        resultActions.andExpect(jsonPath("$.response.products[0].cartItems[0].price").value(50000));

    }
}

์žฅ๋ฐ”๊ตฌ๋‹ˆ ๋‹ด๊ธฐ MOCK ๊ตฌํ˜„


request body

 

1. CartDTO

import lombok.Builder;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;

@Getter @Setter
public class CartDTO{

    private int optionId;
    private int quantity;

    @Builder
    public CartDTO(int optionId, int quantity) {
        this.optionId = optionId;
        this.quantity = quantity;
    }
}

 

์žฅ๋ฐ”๊ตฌ๋‹ˆ์— ๋‹ด๋Š” ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜๊ธฐ ์œ„ํ•ด optionId, quantity ํ•„๋“œ๋ฅผ ํฌํ•จํ•˜๋Š” DTO๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

 

2. Controller

import com.example.kakaoshop._core.utils.ApiUtils;
import com.example.kakaoshop.cart.response.*;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

@RestController
public class CartRestController {

    @PostMapping("/carts/add")
    public ResponseEntity<?> add(@RequestBody List<CartDTO> request) {
        // ์žฅ๋ฐ”๊ตฌ๋‹ˆ ๋‹ด๊ธฐ
        return ResponseEntity.ok(ApiUtils.success(null));
    }

}

 

๋‹ค์Œ์˜ add ๋ฉ”์„œ๋“œ๋Š” "/carts/add" ์—”๋“œํฌ์ธํŠธ๋กœ POST ์š”์ฒญ์„ ๋ฐ›๊ณ , ์š”์ฒญ ๋ฐ”๋””์— ๋‹ด๊ธด CartDTO ๋ฆฌ์ŠคํŠธ๋ฅผ ๋ฐ›์•„์™€ ์žฅ๋ฐ”๊ตฌ๋‹ˆ์— ์ƒํ’ˆ์„ ์ถ”๊ฐ€ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.


์žฅ๋ฐ”๊ตฌ๋‹ˆ ์ˆ˜์ • MOCK ๊ตฌํ˜„


 

 

์™ผ์ชฝ : Request body, ์˜ค๋ฅธ์ชฝ : Response body

 

1. CartUpdateDTO

import lombok.Builder;
import lombok.Getter;
import lombok.Setter;

@Getter @Setter
public class CartUpdateDTO{
    private int cartId;
    private int quantity;

    @Builder
    public CartUpdateDTO(int cartId, int quantity) {
        this.cartId = cartId;
        this.quantity = quantity;
    }
}

 

๋จผ์ € request body์— ๋งž๊ฒŒ cartId์™€ quantity ํ•„๋“œ๊ฐ€ ํ•„์š”ํ•˜๊ธฐ ๋•Œ๋ฌธ์— CartUpdateDTO๋ฅผ ํ†ตํ•ด ๊ตฌํ˜„ํ•œ๋‹ค.

 

2. CartOptionDTO

import lombok.Builder;
import lombok.Getter;
import lombok.Setter;

@Getter @Setter
public class CartOptionDTO {
    private int cartId;
    private int optionId;
    private String optionName;
    private int quantity;
    private int price;

    @Builder
    public CartOptionDTO(int cartId, int optionId, String optionName, int quantity, int price) {
        this.cartId = cartId;
        this.optionId = optionId;
        this.optionName = optionName;
        this.quantity = quantity;
        this.price = price;
    }
}

 

3. CartFinalDTO

import lombok.Builder;
import lombok.Getter;
import lombok.Setter;

import java.util.List;

@Getter @Setter
public class CartFinalDTO{
    private List<CartOptionDTO> carts;
    private int totalPrice;

    @Builder
    public CartFinalDTO(List<CartOptionDTO> carts, int totalPrice) {
        this.carts = carts;
        this.totalPrice = totalPrice;
    }
}

 

4. Controller

@PostMapping("/carts/update")
    public ResponseEntity<?> updateCart(@RequestBody List<CartUpdateDTO> request) {

        List<CartOptionDTO> cartOptionDTOList = new ArrayList<>();

        CartOptionDTO cartOptionDTO1 = CartOptionDTO.builder()
                .cartId(1)
                .optionId(1)
                .optionName("01. ์Šฌ๋ผ์ด๋”ฉ ์ง€ํผ๋ฐฑ ํฌ๋ฆฌ์Šค๋งˆ์Šค์—๋””์…˜ 4์ข…")
                .quantity(10)
                .price(100000)
                .build();
        cartOptionDTOList.add(cartOptionDTO1);

        CartOptionDTO cartOptionDTO2 = CartOptionDTO.builder()
                .cartId(2)
                .optionId(2)
                .optionName("02. ์Šฌ๋ผ์ด๋”ฉ ์ง€ํผ๋ฐฑ ํ”Œ๋ผ์›Œ์—๋””์…˜ 5์ข…")
                .quantity(10)
                .price(109000)
                .build();
        cartOptionDTOList.add(cartOptionDTO2);

        CartFinalDTO responseDTO = CartFinalDTO.builder()
                .carts(cartOptionDTOList)
                .totalPrice(209000)
                .build();

        return ResponseEntity.ok(ApiUtils.success(responseDTO));
    }

 

"/carts/update" ์—”๋“œํฌ์ธํŠธ๋กœ POST request๋ฅผ ๋ฐ›๊ณ , request body์— ๋‹ด๊ธด CartUpdateDTO ๋ฆฌ์ŠคํŠธ๋ฅผ ๋ฐ›์•„์™€ ์žฅ๋ฐ”๊ตฌ๋‹ˆ๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.

 

updateCart ๋ฉ”์„œ๋“œ๋Š” @PostMapping ์–ด๋…ธํ…Œ์ด์…˜์„ ํ†ตํ•ด CartUpdateDTO ๊ฐ์ฒด ๋ฆฌ์ŠคํŠธ๋ฅผ request ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ›๋Š”๋‹ค. ๊ทธ ํ›„ ์žฅ๋ฐ”๊ตฌ๋‹ˆ์˜ ์—…๋ฐ์ดํŠธ๋ฅผ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ํ•˜๊ธฐ ์œ„ํ•ด CartOptionDTO ๊ฐ์ฒด๋“ค์„ ์ƒ์„ฑํ•˜๊ณ  ๋ฆฌ์ŠคํŠธ์— ์ถ”๊ฐ€ํ•œ ๋’ค ๊ฐ ์ •๋ณด๋“ค์„ ์ž…๋ ฅ๋ฐ›๊ณ  ๋งˆ์ง€๋ง‰์œผ๋กœ CartOptionDTO๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ์žฅ๋ฐ”๊ตฌ๋‹ˆ์˜ ์ตœ์ข… ์ƒํƒœ ๋ฐ ์ด ๊ฐ€๊ฒฉ์„ ๋‹ด๋Š”๋‹ค.

 

์š”์•ฝ) controller๋Š” CartUpdateDTO ๋ฆฌ์ŠคํŠธ๋ฅผ request body๋กœ ๋ฐ›์•„ ์žฅ๋ฐ”๊ตฌ๋‹ˆ๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๊ณ , ์ด๋ฅผ CartFinalDTO๋กœ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

 


๊ฒฐ์ œํ•˜๊ธฐ - (์ฃผ๋ฌธ ์ธ์„œํŠธ)


Response body

 

1. ProductDTO

import com.example.kakaoshop.cart.response.CartOptionDTO;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;

import java.util.List;

@Getter
@Setter
public class ProductDTO {

    private String productName;
    private List<CartOptionDTO> items;

    @Builder()
    public ProductDTO( String productName, List<CartOptionDTO> items) {

        this.productName = productName;
        this.items = items;

    }
}

 

2. OrderRespFindAllDTO

import lombok.Builder;
import lombok.Getter;
import lombok.Setter;

@Getter @Setter
public class OrderRespFindAllDTO {
    private int id;
    private ProductDTO products;
    private int totalPrice;

    @Builder()
    public OrderRespFindAllDTO(int id, ProductDTO products, int totalPrice) {
        this.id = id;
        this.products = products;
        this.totalPrice = totalPrice;
    }
}

 

3. Controller

import com.example.kakaoshop._core.utils.ApiUtils;
import com.example.kakaoshop.cart.response.CartOptionDTO;
import com.example.kakaoshop.order.response.OrderRespFindAllDTO;
import com.example.kakaoshop.order.response.ProductDTO;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

@RestController
public class OrderRestController {

    @GetMapping("/orders/{id}")
    public ResponseEntity<?> findById(@PathVariable int id) {

        List<CartOptionDTO> CartOptionDTOList = new ArrayList<>();

        CartOptionDTO option1 = CartOptionDTO.builder()
                .optionId(4)
                .optionName("01. ์Šฌ๋ผ์ด๋”ฉ ์ง€ํผ๋ฐฑ ํฌ๋ฆฌ์Šค๋งˆ์Šค์—๋””์…˜ 4์ข…")
                .quantity(10)
                .price(100000)
                .build();

        CartOptionDTO option2 = CartOptionDTO.builder()
                .optionId(5)
                .optionName("02. ์Šฌ๋ผ์ด๋”ฉ ์ง€ํผ๋ฐฑ ํ”Œ๋ผ์›Œ์—๋””์…˜ 5์ข…")
                .quantity(10)
                .price(109000)
                .build();

        CartOptionDTOList.add(option1);
        CartOptionDTOList.add(option2);

        ProductDTO product1 = ProductDTO.builder()
                .productName("๊ธฐ๋ณธ์— ์Šฌ๋ผ์ด๋”ฉ ์ง€ํผ๋ฐฑ ํฌ๋ฆฌ์Šค๋งˆ์Šค/ํ”Œ๋ผ์›Œ์—๋””์…˜ ์—๋””์…˜ ์™ธ ์ฃผ๋ฐฉ์šฉํ’ˆ ํŠน๊ฐ€์ „")
                .items(CartOptionDTOList)
                .build();

        OrderRespFindAllDTO orderRespFindAllDTO = new OrderRespFindAllDTO(1, product1, 209000);

        return ResponseEntity.ok(ApiUtils.success(orderRespFindAllDTO));
    }

}

ps. ์ฒ˜์Œ์— 2์ฃผ์ฐจ ๊ณผ์ œ ํ•œ ๊ฒŒ์‹œ๊ธ€์— ๋‹ด์œผ๋ ค๊ณ  ์กฐ๊ธˆ์”ฉ ์˜ฌ๋ฆฌ๊ณ  ์ˆ˜์ •ํ•˜๊ณ  ๋ฐ˜๋ณต ์ค‘์ด์—ˆ๋Š”๋ฐ ๋‚ด์šฉ์ด ๋„ˆ๋ฌด ๋งŽ์•„์ ธ์„œ ๊ทธ๋Ÿฐ์ง€ ๊ฐ‘์ž๊ธฐ ์ฐฝ์ด ๋‹ค ๊บผ์ง€๋Š” ์‚ฌํƒœ ๋ฐœ์ƒ..

 

๊ทผ๋ฐ ์ƒˆ ๊ธ€์“ฐ๊ธฐ ํ•˜๋ฉด ๊ณ„์† ์ž„์‹œ์ €์žฅ์ด ๋ผ์„œ ๊ทธ๋™์•ˆ ๊ฐ‘์ž๊ธฐ ์ธํ„ฐ๋„ท ๊บผ์ง€๋Š” ์ƒํ™ฉ์ด์–ด๋„ ๊ดœ์ฐฎ์•˜์—ˆ๋Š”๋ฐ ์˜ค๋Š˜์€ ์ˆ˜์ •์œผ๋กœ ๊ธ€์“ฐ๋‹ˆ๊นŒ ์ž„์‹œ์ €์žฅ ๊ทธ๋Ÿฐ๊ฑฐ ์—†์Œ ..... 3์‹œ๊ฐ„๋™์•ˆ ๋„์„œ๊ด€์—์„œ ์“ด ๊ธ€ ๋‹ค ๋‚ ๋ผ๊ฐ€์„œ ๋‚ด ๋ฉ˜ํƒˆ๋„ ํ•จ๊ป˜ ๋‚ ์•„๊ฐ„ ๊ฒŒ์‹œ๊ธ€์ด๋‹ค ใ…Žใ…Žใ…Ž

 

์•ž์œผ๋กœ๋Š” ๊ผญ ๋Š์–ด์„œ ์จ์•ผ์ง€ ํžˆํžˆ