배경
@WebMvcTest로 Controller 유닛 테스트를 진행하는 과정에서 발생했다.
JPA에서는 엔티티 클래스의 메타데이터를 이용하여 쿼리를 생성하기 때문에, 이 메타데이터를 담은 메타모델 클래스가 필요하다. JPA metamodel must not be empty 오류는 JPA 엔티티 클래스에 대한 메타모델 클래스가 생성되지 않은 경우 발생한다.
테스트에 필요한 Bean들은 모두 주입 받았다고 생각했는데 왜 이런 에러가 발생했을까?
원인
Auditing을 통한 생성일, 수정일 자동 생성을 구현하면서 @EnableJpaAuditing 애너테이션을 Application 위에 올려서 사용하고 있었다.
@EnableJpaAuditing
@SpringBootApplication
public class TravelWithMeApplication {
public static void main(String[] args) {
SpringApplication.run(TravelWithMeApplication.class, args);
}
}
Application 위에 @EnableJpaAuditing 을 사용하면 Jpa 관련 Bean도 요구하게 된다. 내가 테스트에서 사용한 @WebMvcTest는 Mvc와 관련된 Bean들만 찾아서 주입해주기 때문에 Jpa 관련 Bean을 찾지 못해서 JPA metamodel must not be empty 에러가 발생했던 것이다.
해결
첫 번째 방법. @MockBean
Test 클래스에 @MockBean(JpaMetamodelMappingContext.class) 애너테이션을 추가하여 Bean 주입을 해준다. 하지만 이 방식은 Test 클래스마다 해당 애너테이션을 붙여줘야하는 번거로움이 있다.
@WebMvcTest(controllers = MemberController.class)
@MockBean(JpaMetamodelMappingContext.class) // 추가
class MemberControllerTest {
...
}
두 번째 방법. Configuration 분리
Configuration을 Application에서 분리해서 @WebMvcTest에서 Jpa 관련 Bean을 요구할 일이 없도록 만든다.
@EnableJpaAuditing
@Configuration
public class JpaAuditingConfig {
}
다만 Configuration을 분리하면 Auditing을 사용하는 클래스에서 @DataJpaTest 테스트할 때는 별도 추가 설정을 해주어야 한다. @DataJpaTest는 Jpa 관련 Bean만 가져오는데 별도 Configuration Bean은 가져오지 않기 때문에 @Import(JpaAuditingConfig.class) 애너테이션을 추가해주어야 한다.
@DataJpaTest
@Import(JpaAuditingConfig.class) // 추가
class MemberRepositoryTest {
...
}
'나의 에러 일지' 카테고리의 다른 글
Java - Java 8 Local Date Time 직렬화/역직렬화 에러 원인과 해결 방법 (0) | 2023.04.11 |
---|---|
Spring - non null key required 원인과 해결 방법 (0) | 2023.04.10 |
Spring - @Value가 계속 null을 가져올 때 원인과 해결 방법 (6) | 2023.04.02 |
Spring - Spring Security 적용시 순환 참조 발생 (Spring circular reference) (0) | 2023.03.31 |
Spring Security - io.jsonwebtoken.security.WeakKeyException 원인과 해결 방법 (0) | 2023.03.27 |