항해99/개발일지

20220209 개발일지 #MVC Test

paran21 2022. 2. 9. 21:16

어제 구현한 RestaurantMvcTest에 이어 FoodMvcTest와 OrderMvcTest를 만들었다.

RestaurantMvcTest에 조금 변형만 하면 되는 거라서 금방 될 줄 알았는데 에러를 해결하는데 생각보더 훨씬 시간이 걸렸다.

 

FoodMvcTest를 작성할 때 음식 등록 api에서 400에러가 발생하였다.

권한 설정으로 발생하는 403 에러가 아니라서 처음에는 서비스 로직을 의심했다.

혹시 리팩토링을 하면서 문제가 생겼는지 확인했는데, arc에서 잘 돌아가는 것을 확인했다.

그래서 restaurantId가 pathvariable로 들어가는데 restaurant를 생성하지 않아서 발생한 에러라고 생각했다.

 

다른 test code들을 확인하면서 음식점을 등록하는 테스트를 먼저 만들어주고, 여기서 받은 restaurant를 가져와서 id로 넣으려 하였다.

그런데 restaurant가 계속 null값이 찍히고 제대로 들어가지 않았다.


※ Test code에 Dto 생성자 필요한 경우 : @AllArgsConstructor 사용하기

이 과정에서 이전에 Dto로 넣은 값들이 모두 제대로 들어가지 않고 값이 null값이 되는 것을 확인했다.

Dto에 생성자를 만들어줬는데 이게 변환과정에서 변수명이 바뀌고, 변수를 찾지 못하면서 null로 되는 것 같다.

RestaurantDto restaurantDto = new RestaurantDto(
        name, minOrderPrice, deliveryFee, x, y
);

@AllArgsConstructor를 사용하여 해결했다.


@MockBean도 써보고 response를 받는 방법도 찾아봤는데 해결이 계속 안됬다.

 

그런데!! 생각해보니 restaurantId를 못찾으면 NullpointerException에서 설정해놓은 error메시지가 떠야할 것 같은데 errormessage는 null로 나왔다!

(오늘 확인해봤는데 mvc test라서 그런지 service 이후에 발생하는 에러는 제대로 test가 되지 않는 것 같다.

의도적으로 에러 값을 넣어도 테스트가 통과되었다.

에러 부분은 integration test나 unit test로 진행해야 할 것 같다) 

그리고 음식 조회는 테스트가 제대로 동작하는 것을 확인하였다.

 

어제 restaurant도 입력값을 빼먹어서 에러가 떴었고, 오늘 food하면서 확인한다고 했는데도 이 부분을 빼먹은 거였다.. List<FoodDto>로 해야했는데 FoodDto라서 에러가 난 거였다.

 

Order의 경우 입력값도 다시 확인을 잘해서 테스트가 잘 실행되는 것을 확인했다.

 

@WebMvcTest(value = FoodController.class)
public class FoodMvcTest {
    @Autowired
    private MockMvc mvc;

    @Autowired
    private ObjectMapper objectMapper;

    Long restaurantId = 1L;

    @MockBean
    FoodService foodService;

    @Nested
    @DisplayName("음식 등록")
    class RegistFood {

        @Test
        @WithMockUser(roles = "ADMIN")
        @DisplayName("신규 음식 등록_ADMIN")
        void test1() throws Exception {

            // given
            String name = "초밥정식";
            Long price = 10000L;
            FoodDto foodDto = new FoodDto(name, price);
            List<FoodDto> foodDtoList = new ArrayList<>();
            foodDtoList.add(foodDto);

            String postInfo = objectMapper.writeValueAsString(foodDtoList);

            // when - then
            mvc.perform(post("/restaurant/" + restaurantId + "/food/register")
                            .content(postInfo)
                            .contentType(MediaType.APPLICATION_JSON)
                            .accept(MediaType.APPLICATION_JSON)
                    )
                    .andExpect(status().isOk())
                    .andDo(print());

        }

        @Test
        @WithMockUser(roles = "USER")
        @DisplayName("신규 음식 등록_USER")
        void test2() throws Exception {

            // given
            String name = "초밥정식";
            Long price = 10000L;
            FoodDto foodDto = new FoodDto(name, price);
            List<FoodDto> foodDtoList = new ArrayList<>();
            foodDtoList.add(foodDto);

            String postInfo = objectMapper.writeValueAsString(foodDtoList);

            // when - then
            mvc.perform(post("/restaurant/" + restaurantId + "/food/register")
                            .content(postInfo)
                            .contentType(MediaType.APPLICATION_JSON)
                            .accept(MediaType.APPLICATION_JSON)
                    )
                    .andExpect(status().isForbidden())
                    .andDo(print());

        }
    }
    @Nested
    @DisplayName("음식 조회")
    class GetFood {

        @Test
        @WithMockUser(roles = "ADMIN")
        @DisplayName("음식 조회_ADMIN")
        void test3() throws Exception {
            mvc.perform(get("/restaurant/" + restaurantId + "/foods"))
                    .andExpect(status().isForbidden())
                    .andDo(print());
        }

        @Test
        @WithMockUser(roles = "USER")
        @DisplayName("음식 조회_USER")
        void test4() throws Exception {
            mvc.perform(get("/restaurant/" + restaurantId + "/foods"))
                    .andExpect(status().isOk())
                    .andDo(print());
        }

    }
}
@WebMvcTest(value = OrderController.class)
public class OrderMvcTest {
    @Autowired
    private MockMvc mvc;

    @Autowired
    private ObjectMapper objectMapper;

    @MockBean
    OrderService orderService;

    @Nested
    @DisplayName("주문 등록")
    class RegistOrder {

        @Test
        @WithMockUser(roles = "ADMIN")
        @DisplayName("주문 등록_ADMIN")
        void test1() throws Exception {

            // given
            Long restaurantId = 1L;
            Long x = 3L;
            Long y = 4L;
            Long id = 1L;
            Long quantity = 2L;
            OrderDto.Foods orderFood = new OrderDto.Foods(id, quantity);
            List<OrderDto.Foods> orderFoodList = new ArrayList<>();
            orderFoodList.add(orderFood);
            OrderDto orderDto = new OrderDto(restaurantId, x, y, orderFoodList);

            String postInfo = objectMapper.writeValueAsString(orderDto);

            // when - then
            mvc.perform(post("/order/request")
                            .content(postInfo)
                            .contentType(MediaType.APPLICATION_JSON)
                            .accept(MediaType.APPLICATION_JSON)
                    )
                    .andExpect(status().isForbidden())
                    .andDo(print());

        }

        @Test
        @WithMockUser(roles = "USER")
        @DisplayName("주문 등록_USER")
        void test2() throws Exception {
            // given
            Long restaurantId = 1L;
            Long x = 3L;
            Long y = 4L;
            Long id = 1L;
            Long quantity = 2L;
            OrderDto.Foods orderFood = new OrderDto.Foods(id, quantity);
            List<OrderDto.Foods> orderFoodList = new ArrayList<>();
            orderFoodList.add(orderFood);
            OrderDto orderDto = new OrderDto(restaurantId, x, y, orderFoodList);

            String postInfo = objectMapper.writeValueAsString(orderDto);

            // when - then
            mvc.perform(post("/order/request")
                            .content(postInfo)
                            .contentType(MediaType.APPLICATION_JSON)
                            .accept(MediaType.APPLICATION_JSON)
                    )
                    .andExpect(status().isOk())
                    .andDo(print());

        }

        @Nested
        @DisplayName("주문 조회")
        class GetOrder {

            @Test
            @WithMockUser(roles = "ADMIN")
            @DisplayName("주문 조회_ADMIN")
            void test3() throws Exception {
                mvc.perform(get("/orders"))
                        .andExpect(status().isForbidden())
                        .andDo(print());
            }

            @Test
            @WithMockUser(roles = "USER")
            @DisplayName("주문 조회_USER")
            void test4() throws Exception {
                mvc.perform(get("/orders"))
                        .andExpect(status().isOk())
                        .andDo(print());
            }
        }

    }
}

정말 에러 찾는데 오래걸렸지만 우선 목표한 test code는 잘 작성한 것 같다.

errormessage는 예외 처리한 테스트해보면서 다시 확인해보면 될 것 같다.