기능 구현을 완료한 다음 컨트롤러 부분 테스트 코드를 짜는 중이었다...
컨트롤러 부분만 테스트 코드를 짜면 되니까 이제 금방 끝날 줄 알고 행복한 마음으로 룰루랄라 짜고 있던 도중 생각지도 못한 난관에 부딪히게 됐다
@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으로 항상 명시를 해주자!
'Spring' 카테고리의 다른 글
동적쿼리와 인덱싱 적용하여 성능 개선하기 (+ Like 검색은?) (0) | 2025.04.07 |
---|---|
QClass 구현 안 될때 해결법 (0) | 2025.04.04 |
QueryDSL을 이용하여 동적 쿼리 구현하기 (0) | 2025.03.31 |
조회수 및 어뷰징 방지 Redis로 구현하기 (0) | 2025.03.30 |
failed to create jar file 문제 해결하기 (1) | 2025.03.25 |