@EnableJpaAuditing과 @SpringBootApplication 을 같이 쓸때, Test에서 발생되는 에러
상황
현재 Spring Boot 프로젝트의 진입점인 main 함수 부분이다.
아래와 같이 Auditing 기능을 사용하기 위해
@EnableJpaAuditing 애노테이션을 붙여줬다.
WiseSayingApplication.class
@EnableJpaAuditing // 문제 부분
@SpringBootApplication
public class WiseSayingApplication {
private static ApplicationContext applicationContext;
public static void main(String[] args) {
applicationContext = SpringApplication.run(WiseSayingApplication.class, args);
displayAllBeans();
}
public static void displayAllBeans() {
String[] allBeanNames = applicationContext.getBeanDefinitionNames();
for(String beanName : allBeanNames) {
System.out.println(beanName);
}
}
}
그리고 아래와 같이 Controller 레벨의 슬라이스 테스트를 하려고
@WebMvcTest 애노테이션을 붙여줬다.
해당 애노테이션은 Controller 레벨의 슬라이스만 가능하도록 필요한 빈들을 등록시켜주고 그런 역할을 한다.
한마디로 @SpringbooteTest보다 가볍다.
MemberControllerTest.class
@WebMvcTest(MemberController.class) // 문제 부분
@AutoConfigureMockMvc
public class MemberControllerTests {
@Autowired
MockMvc mockMvc;
@Autowired
Gson gson;
MediaType mediaType = MediaType.APPLICATION_JSON;
:
:
@Test
void postMemberTest() throws Exception {
MemberDto.Post post = new MemberDto.Post();
post.setEmail("january@gmail.com");
post.setName("멋쟁이");
post.setPhone("010-2222-3333");
:
:
}
}
출력 에러
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jpaAuditingHandler': Cannot resolve reference to bean 'jpaMappingContext' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jpaMappingContext': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: JPA metamodel must not be empty!
:
:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jpaMappingContext': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: JPA metamodel must not be empty!
:
:
Caused by: java.lang.IllegalArgumentException: JPA metamodel must not be empty!
중요한 에러는 위에 세줄이다.
발생 이유
@EnableJpaAuditing 은 기본적으로 Jpa관련 빈들을 필요로한다.
그런데 @SpringBootApplication과 같이 사용하면 @EnableJpaAuditing 애노테이션 기능을 바로 활성화 한다.
그러므로 Jpa 관련 빈들을 찾아서 사용하려고 할것이다.
그런데 위에서 보았다시피 나는 Test에서 Controller 레벨의 테스트만을 위해 @WebMvcTest(MemberController.class)
애노테이션을 사용하였다. 그러므로 Jpa 관련 빈들은 등록하지 않는다.
즉,
@EnableJpaAuditing 을 @SpringBootApplication 과 같이 쓰면
@EnableJpaAuditing 애노테이션 기능이 활성화 되면서
Jpa 관련 빈들을 사용하려고 하는데,
Test시에 Jpa 관련 빈들을 등록 하지 않았기 때문에 에러.
해결 방법
1. @Configuration 분리
JpaAuditingConfig.java
@EnableJpaAuditing
@Configuration
public class JpaAuditingConfig {
}
2. @MockBean 추가
WebMvcTest.java
@RunWith(SpringRunner.class)
@WebMvcTest(TargetController.java)
@MockBean(JpaMetamodelMappingContext.class)
테스트 클래스에 JpaMetamodelMappingContext를 MockBean으로 추가한다.
2번처럼 매번 WebMvcTest마다 @MockBean을 추가해주는 방법보다는 1번 처럼 Configuration을 분리해주는 방식이 더 편한 것 같다.
3. 테스트시에 @WebMvcTest 대신에 그냥 @SpringBootApplication 사용한다
제일 간단.
그리고 서비스단과 연결을 끊어주려면 그냥 service 객체는 @MockBean 을 사용하여 만들자.
새로운 문제점
1번 해결방법을 사용하면 모든게 해결이 될 줄알았다. 그런데 @DataJpaTest를 사용할 때 문제가 발생했다.
상황은 createdAt을 가지고 있는 Article 클래스가 있다.
@DataJpa를 이용한 테스트
createdAt이 null이다.
save 후에도 null이 들어왔다.
@DataJpaTest는 JpaTest에 필요한 최소한의 빈을 불러오는데, 거기에는 @Configuration 빈이 포함되어있지 않다.
따라서 @Configuration을 사용하여 따로 설정 파일을 만들었을 경우 아래 사진처럼 Import(JpaAuditingConfig.class)를 넣어줘야 한다.
참조 : https://giron.tistory.com/127
[JPA]JpaAuditing을 Application 위에 쓰면 안되는 이유
@WebMvcTest를 붙이고 테스트를 돌리니 JPA metamodel must not be empty! 와 같은 에러가 발생했다. 이유를 찾아보니 테스트를 돌릴때는 기본적으로 XApplication이 돌면서 작동한다. 따라서 @EnableJpaAuditing..
giron.tistory.com
JUnit 테스트 에러 : JPA metamodel must not be empty!
JUnit 테스트코드 중 @WebMvcTest(특정클래스.class)를 붙인 Controller 클래스를 run할 때 생기는 오류이다. 이는 JPA에서도 @EnableJpaAuditing을 추가했는데 @WebMvcTest가 JPA 관련 Bean들을 로드하지 않기 때문에
velog.io