에러 : JPA metamodel must not be empty! 해결기

최지환·2023년 2월 13일
4

프로젝트-모각코

목록 보기
7/7
post-thumbnail

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를 좀 찾아보았고, 다음과 같은 특징에 대해 알게되었다.

  • @WebMvcTest 사용 시 SpringMvc 컴포넌트들만 적용한다.
    • 스프링 관련 모든 자동 구성이 비활성화 되고, MVC테스트와 관련된 구성만 적용된다.
    • ex) @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를 사용하였기 때문에, 이런 방식은 올바르지 않다고 생각했다.

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


해결 방법

방법은 두가지가 있다.

  1. Configuration 설정을 별도 분리하여 @EnableJpaAuditing를 분리한다.
  2. 테스트 코드에 JpaMetaModelMappingContext 클래스의 MockBean을 추가한다.

방법1 .Configuration 설정을 별도 분리하여 @EnableJpaAuditing를 분리

Configuration 설정을 별도 분리한다면, Configuration 파일이 빈으로서 등록되지 않을 것이고 테스트 코드 실행 시 Application이 JPA와 상관없이 정상 실행하게 된다.

@Configuration 어노테이션 내부에 @Component가 있기 때문에, @WebMvcTest는 해당 설정 파일을 빈으로서 등록하지 않는다.

방법3. 테스트 코드에 JpaMetaModelMappingContext 클래스의 MockBean을 추가

이 방법은 테스트 코드 실행 시 자동으로 JpaMetaModelMappingContext을 빈으로 등록하게 한다.

위와 같이 등록을 하게 되면 Jpa -Auditing 설정에 대한 컨텍스트가 등록되고 테스트 코드가 동작한다.


나는 방법 1을 선택했다.

이유

  • 2번의 방법은 @WebMvcTest를 사용하는 곳이면 Auditing 에 관련 없는 Controller의 테스트에도, 매번 @MockBean(JpaMetamodelMappingcontest.class)를 적어줘야하기 때문
  • 1번의 방법은 코드를 한번 분리함으로서 테스트 코드에서 JPA-Auditing 관련 의존성을 제거할 수 있기 때문

0개의 댓글