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 어노테이션을 달아둔 것이 문제였다.

스크린샷 2022-11-15 오후 11.39.50.png

좀 더 자세히 말하자면,Controller 를 테스트 하기 위해 Test 코드 내부에 @WebMvcTest 를 사용했다.

@WebMvcTest를 좀 찾아보았고, 다음과 같은 특징에 대해 알게되었다.

정리하자면 @WebMvcTest를 사용한다면 @Controller를 포함한 SpringMVC레벨의 컴포넌트들이 적용된다. 이때 @Component, @Service , @Repository 는 적용이 안된다.

따라서 테스트 실행 시 JPA-Auditing 관련 빈이 등록이 안된 상태로 Application 에 있던 @EnableJpaAuditing 어노테이션이 실행되었고, 이로인해 JPA metamodel must not be empty! 라는 에러를 불러일으켰다.

만약 @SpringBootTest 를 사용해서 전체 컨텍스트를 로드하면서 모든 빈을 주입받으면 에러가 발생하지 않았지만, Controller 만을 테스트하기 위해서 @WebMvcTest를 사용하였기 때문에, 이런 방식은 올바르지 않다고 생각했다.

그럼 어떻게 해결해야할까?


해결 방법

방법은 두가지가 있다.