읭?! 전체 테스트 시 하나 실패 (auto_increment);;

엉금엉금·2022년 7월 20일
0

오늘 만난 문제

목록 보기
17/24

개별적으로 작성한 테스트 코드가 모두 실행했을 때, 하나가 실패한다.

한 클래스에 작성한 개별적인 테스트 메서드들을 동시에 모두 실행했을 경우 순서를 보장하지 않는다고 한다. 그리고 전체 테스트를 실행했을 때, 한 테스트가 다른 테스트에 영향을 주어선 안되고 독립적이여야 한다.

@BeforeEach
void clear() {
	restaurantRepository.deleteAll();
}

이를 위해서 @BeforeEach 어노테이션을 붙인 메소드를 사전에 만들었다.
위와 같이 메소드를 만들면 개별적인 테스트들이 수행되기 전에 @BeforeEach를 붙인 메서드가 동작해 테스트 메서드들이 서로 영향을 미치지 않는다. 그럼에도 불구하고 제일 위의 사진과 같은 테스트 검증 실패를 보게 되었다. 아무래도 DB의 데이터를 지우는 것은 문제가 아닌 것 같다는 생각이 들었다.

Body = {"code"="400", "message"="존재하지 않는 음식점입니다"}

    @Test
    @DisplayName("POST 특정 음식점 메뉴 등록")
    void saveFoods() throws Exception {

        // given
        Restaurant restaurant = Restaurant.builder()
                .name("쉐이크쉑 청담점")
                .minOrderPrice(5000)
                .deliveryFee(2000)
                .build();

        final Long restaurantId = 1L;

        restaurantRepository.save(restaurant);

        List<SaveFoodDto> foods = new ArrayList<>();
        foods.add(new SaveFoodDto("쉑버거 더블", 10900));
        foods.add(new SaveFoodDto("치즈 감자튀김", 4900));
        foods.add(new SaveFoodDto("쉐이크", 5900));
        SaveFoodRequestDto request = new SaveFoodRequestDto(foods);

        String json = objectMapper.writeValueAsString(request);

        // when
        mockMvc.perform(post("/api/v1/restaurants/{restaurantId}/foods", restaurantId)
                        .contentType(APPLICATION_JSON)
                        .content(json))
                .andExpect(status().isOk()) // **검증 실패 지점**
                .andDo(print());

        // then
        ...
    }

응답 'Body'를 단서로 전체 테스트 실행했다. (검증 기능 나름 디테일하게 잘 만들어놓길 잘했다는 생각이 들었다 허허허) 하지만 그 전에 'String json'이 만들어지는 시점에 Break Point를 하나 걸어두었다. 'restaurantId'가 의심스러웠다.

Debug 창에서 Evaluate Expression을 통해서 DB에 저장되어 있는 음식점을 검색해보았다. 이를 통해서 내가 예상했던 'restaurantId'가 1인 것과 실제 저장된 음식점의 인공키인 'id'가 2인 것이 다른게 문제였다는 것을 확인할 수 있었다.

@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "RESTAURANT_ID")
    private Long id;

음식점의 id는 'Auto increment'이다. 개별적인 테스트코드를 실행했을 때는 DB에 저장했을 시, 모두 id가 1임을 확실히 보장할 수 있지만 전체를 모두 실행했을 때는 실행 순서를 보장 받을 수 없다. 또한 @BeforeEach를 통해 DB의 내용을 모두 지운다해도 id는 이전의 값으로 저장되지 않는다. (물론 방법이 있다곤 한다 여기를 참고!! 여기가 완벽한 해법이 아닐 수도 있다;;)

결국 나는 아래와 같이 코드를 수정했다.

    @Test
    @DisplayName("POST 특정 음식점 메뉴 등록")
    void saveFoods() throws Exception {

        // given
        Restaurant restaurant = Restaurant.builder()
                .name("쉐이크쉑 청담점")
                .minOrderPrice(5000)
                .deliveryFee(2000)
                .build();

        restaurant = restaurantRepository.save(restaurant); // 수정!!!!!!!!!!!!!!!!!!
        final Long restaurantId = restaurant.getId();


        List<SaveFoodDto> foods = new ArrayList<>();
        foods.add(new SaveFoodDto("쉑버거 더블", 10900));
        foods.add(new SaveFoodDto("치즈 감자튀김", 4900));
        foods.add(new SaveFoodDto("쉐이크", 5900));
        SaveFoodRequestDto request = new SaveFoodRequestDto(foods);

        String json = objectMapper.writeValueAsString(request);

        // when
        mockMvc.perform(post("/api/v1/restaurants/{restaurantId}/foods", restaurantId)
                        .contentType(APPLICATION_JSON)
                        .content(json))
                .andExpect(status().isOk())
                .andDo(print());

        // then
        ...
    }

코드는 설명하지 않아도 될 만큼 간단하지만ㅋㅋ DB에 저장한 음식점의 id를 바로 받아 'restaurantId'에 값을 넣어주는 것이다.

업로드중..

이후 전체 테스트를 실행했을 때, 모든 테스트가 성공하는 것을 확인했다!


글 작성 후, 구글링 좀 더 해보았는데;;; 참고해준 URI뿐만이 아닌 여러가지 방법들이 존재하고 있었다. 아직도 많이 부족함을 느끼고 더 나아가야 함을 느꼈다. 파이팅!!

profile
step by step

0개의 댓글