@WebMvcTest 환경 테스트 중 발생한 jpaAuditingHanlder Error
@WebMvTest
환경에서 테스트를 하다가 jpaAuditingHandler
Error가 발생하여 발생 원인과 해결 방법을 기록하기위해 이 글을 작성하였다.
문제가 발생한 Test Code
@WebMvcTest
@AutoConfigureMockMvc
@Import({ SecurityConfig.class, UserIdHeaderValidationFilterTest.DummyController.class })
class UserIdHeaderValidationFilterTest {
@RestController
static class DummyController {
@GetMapping("/test")
public ResponseEntity<String> test() {
return ResponseEntity.ok("OK");
}
}
@Autowired
private MockMvc mockMvc;
@Test
@WithMockUser
public void 헤더에_X_USER_ID가_없으면_401_에러가_발생한다() throws Exception {
mockMvc.perform(get("/"))
.andExpect(status().is(HttpStatus.UNAUTHORIZED.value()));
}
@Test
public void 헤더에_X_USER_ID가_있으면_200_응답을_반환한다() throws Exception {
mockMvc.perform(get("/test").header("X-USER-ID", "1"))
.andExpect(status().isOk());
}
}
테스트 목적은 단순히 Spring Security에 등록한 필터가 정상적으로 작동하는지 확인하는 테스트였으며, API에 요청 후 단순 status값만 확인하면 되는 간단한 테스트 였다.
하지만 test는 생각하지도 못한 이유로 실패 하였으며 에러는 다음과 같았다.
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jpaAuditingHandler': Cannot resolve reference to bean 'jpaMappingContext' while setting constructor argument
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:377) ~[spring-beans-6.2.1.jar:6.2.1]
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:135) ~[spring-beans-6.2.1.jar:6.2.1]
at org.springframework.beans.factory.support.ConstructorResolver.resolveConstructorArguments(ConstructorResolver.java:691) ~[spring-beans-6.2.1.jar:6.2.1]
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:513) ~[spring-beans-6.2.1.jar:6.2.1]
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jpaMappingContext': JPA metamodel must not be empty
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1808) ~[spring-beans-6.2.1.jar:6.2.1]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:601) ~[spring-beans-6.2.1.jar:6.2.1]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:523) ~[spring-beans-6.2.1.jar:6.2.1]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:336) ~[spring-beans-6.2.1.jar:6.2.1]
로그를 확인한 결과 jpaAuditingHandler
Error가 발생하여 실패 했던것이다.
나는 해당 에러를 보고 한참동안 의아했었다.
왜냐면 프로젝트에 JpaAuditing 기능을 사용 하고있는건 맞지만 테스트하는 Filter나 Test Code 내에서 Jpa관련된 어느한 작업도 하지않고 사용하지도 않기 때문이다.
에러 원인
에러 원인을 찾아본 결과 main method가 존재하는 클래스에서 @EnableAuditing
을 선언하였기 때문이고, Test Code가 실행될 때 JPA-Auditing 관련된 Bean이 Bean Container에 등록되지 않아 에러가 발생 했던것이다.
@EnableJpaAuditing
@SpringBootApplication
public class MessengerServiceApplication {
public static void main(String[] args) {
SpringApplication.run(MessengerServiceApplication.class, args);
}
}
@WebMvcTest
같은 경우에는 스프링 관련 모든 자동 구성이 비활성화 되고, MVC테스트와 관련된 @Controller
, @RestController
, @Filter
, @ControllerAdvice
같은 것들만 Bean으로 등록한다.
따라서 Test가 실행되면서 JPA-Auditing
과 관련 Bean이 등록이 안된 상태로 Application에 있던 @EnableJpaAuditing
어노테이션이 적용되어 에러를 발생시킨거다.
해결 방법
나는 main method가 있는 클래스에서 @EnableAuditing
을 제거하고 JPA-Auditing
을 담당하는 config 객체 JpaAuditingConfig
객체를 생성해 분리함으로써 해결 했다.
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
@Configuration
@EnableJpaAuditing
public class JpaAuditingConfig {
// AuditorAware 등 관련 빈 등록
}
또 다른 해결 방법
또 다른 방법으로는 Test Code에 JpaMetaModelMappingContext
를 빈으로 등록하면 JPA-Auditing 관련된 Bean이 테스트를 실행할 떄 자동으로 등록이 된다고 한다.
참고
https://everydayidid.tistory.com/77
https://velog.io/@cjh8746/에러-JPA-metamodel-must-not-be-empty-해결기