Controller 를 테스트 하면서 jpa metamodel must not be empty! 라는 에러 메세지를 만났다.
@WebMvcTest(UserController.class)
class UserControllerTest {
@Autowired
private MockMvc mockMvc;
@Autowired
private ObjectMapper objectMapper;
@MockBean
private UserService userService;
@Test
@DisplayName("회원 가입을 한다.")
void join() throws Exception {
//given
Map<String, String> input = new HashMap<>();
input.put("loginId", "apple123");
input.put("password", "apple123!");
input.put("alias", "아이폰");
//when
ResultActions actual = mockMvc.perform(
post("/api/user/join").contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(input)));
//then
actual.andExpect(status().isOk());
}
}
테스트 코드를 작성 할때 JPA 관련 설정을 건들지는 않아서, 이런 문제가 왜 발생했는지 찾아보았더니, 이전에 Auditing 설정[엔티티의 생성 시점에서 자동으로 LocalDateTime을 가진 BaseEntity 생성]을 하면서 Application 에 @EnableJpaAuditing 어노테이션을 달아둔 것이 문제였다.

좀 더 자세히 말하자면,Controller 를 테스트 하기 위해 Test 코드 내부에 @WebMvcTest 를 사용했다.
@WebMvcTest를 좀 찾아보았고, 다음과 같은 특징에 대해 알게되었다.
@Controller, @ControllerAdvice, @JsonComponent, Converter/GenericConverter, Filter, WebMvcConfigurer그리고HandlerMethodArgumentResolve 등이 적용@Component, @Service , @Repository 는 적용이 안됨.정리하자면 @WebMvcTest를 사용한다면 @Controller를 포함한 SpringMVC레벨의 컴포넌트들이 적용된다. 이때 @Component, @Service , @Repository 는 적용이 안된다.
따라서 테스트 실행 시 JPA-Auditing 관련 빈이 등록이 안된 상태로 Application 에 있던 @EnableJpaAuditing 어노테이션이 실행되었고, 이로인해 JPA metamodel must not be empty! 라는 에러를 불러일으켰다.
만약 @SpringBootTest 를 사용해서 전체 컨텍스트를 로드하면서 모든 빈을 주입받으면 에러가 발생하지 않았지만, Controller 만을 테스트하기 위해서 @WebMvcTest를 사용하였기 때문에, 이런 방식은 올바르지 않다고 생각했다.
그럼 어떻게 해결해야할까?
방법은 두가지가 있다.