본문 바로가기

Spring

컨트롤러 테스트 작성시 주의할 점

기능 구현을 완료한 다음 컨트롤러 부분 테스트 코드를 짜는 중이었다...

컨트롤러 부분만 테스트 코드를 짜면 되니까 이제 금방 끝날 줄 알고 행복한 마음으로 룰루랄라 짜고 있던 도중 생각지도 못한 난관에 부딪히게 됐다

@WebMvcTest(DoctorController.class)
class DoctorControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @MockitoBean
    private DoctorService doctorService;


    @Test
    public void 의사_단건_조회() throws Exception {
        // given
        long userId = 1L;
        String username = "kimdoctor";
        String major = "INTERNAL_MEDICINE";
        String imageUrl = "https://example.com/image.jpg";
        LocalTime startTime = LocalTime.of(9, 0);
        LocalTime endTime = LocalTime.of(18, 0);

        BDDMockito.given(doctorService.findDoctor(userId)).willReturn(new DoctorResponse(userId, username, major, imageUrl, startTime, endTime));

        // when & then
        mockMvc.perform(get("/api/v1/doctors/{id}", userId))
                .andExpect(status().isOk())
                .andExpect(MockMvcResultMatchers.jsonPath("$.data[0].id").value(userId))
                .andExpect(MockMvcResultMatchers.jsonPath("$.data[0].name").value(username))
                .andExpect(MockMvcResultMatchers.jsonPath("$.data[0].imageUrl").value(imageUrl));
    }

 

이렇게 짜고 실행을 했는데!!!!

 

문제 1 : JPA metamodel must not be empty

Caused by: java.lang.IllegalArgumentException: JPA metamodel must not be empty at org.springframework.util.Assert.notEmpty(Assert.java:398)

 

오류가 뜨는 것이다!!

 

찾아보니 JPA 메타모델 클래스가 없거나 빈 경우에 발생하는 에러라는데 컨트롤러 테스트인데 도대체 왜 이 에러가 발생하는 것인지 곰곰히 생각을 해봤는데

 

처음에 생성일이랑 수정일 업데이트를 위해서 @EnableJpaAuditing를 붙였던 것이다!!

즉, @EnableJpaAuditing은 jpa속성이기 때문에 이와 관련된 설정을 @MockitoBean으로 넣어줘야 한다

@SpringBootApplication
@EnableJpaAuditing
@EnableSpringDataWebSupport(pageSerializationMode = VIA_DTO)
public class DocconnetingApplication {

 

이걸 추가해줬더니 이 문제는 해결이 됐다

    @MockitoBean
    JpaMetamodelMappingContext jpaMetamodelMappingContext;

 

문제 2 : 응답 객체 값이 비었다고 뜸

 

작성한 코드를 실행시켜봤더니

@Test
    public void 의사_다건_조회() throws Exception {
    	// 테스트 코드..
        // when & then
        mockMvc.perform(get("/api/v1/doctors?page=1&size=10&category=INTERNAL_MEDICINE")
                .andExpect(status().isOk())
                .andExpect(MockMvcResultMatchers.jsonPath("$.data[0].id").value(user1.getId()))
                .andExpect(MockMvcResultMatchers.jsonPath("$.data[0].name").value(user1.getUsername()))
                .andExpect(MockMvcResultMatchers.jsonPath("$.data[1].id").value(user2.getId()))
                .andExpect(MockMvcResultMatchers.jsonPath("$.data[1].name").value(user2.getUsername()))
                .andExpect(MockMvcResultMatchers.jsonPath("$.page.pageNum").value(page))
                .andExpect(MockMvcResultMatchers.jsonPath("$.page.pageSize").value(size))
                .andExpect(MockMvcResultMatchers.jsonPath("$.page.totalElement").value(totalElement))
                .andExpect(MockMvcResultMatchers.jsonPath("$.page.totalPage").value(totalPages));
    }

 

음? PageResult의 content값이 비었다고 하는 에러가 발생했다

하지만 아무리 생각해봐도 코드단에서는 문제가 전혀 없었는데 왜 이런가 찾아보니..

쿼리 파라미터 값도 명시적으로 작성해야 하는 것이었다!!

이렇게 파라미터를 명시적으로 작성해주면 해결된다

// when & then
        mockMvc.perform(get("/api/v1/doctors")
                .param("page", String.valueOf(page))
                .param("size", String.valueOf(size))
                .param("category", "")
                .param("name", ""))
                .andExpect(status().isOk())
                .andExpect(MockMvcResultMatchers.jsonPath("$.data[0].id").value(user1.getId()))
                .andExpect(MockMvcResultMatchers.jsonPath("$.data[0].name").value(user1.getUsername()))
                .andExpect(MockMvcResultMatchers.jsonPath("$.data[1].id").value(user2.getId()))
                .andExpect(MockMvcResultMatchers.jsonPath("$.data[1].name").value(user2.getUsername()))
                .andExpect(MockMvcResultMatchers.jsonPath("$.page.pageNum").value(page))
                .andExpect(MockMvcResultMatchers.jsonPath("$.page.pageSize").value(size))
                .andExpect(MockMvcResultMatchers.jsonPath("$.page.totalElement").value(totalElement))
                .andExpect(MockMvcResultMatchers.jsonPath("$.page.totalPage").value(totalPages));
    }

 

결론

  • 컨트롤러 테스트를 할 때는 jpa관련 설정을 한게 있는지 항상 주의하고 또 주의하자!
  • 쿼리 파라미터가 들어간 경우에는 param으로 항상 명시를 해주자!