관리 메뉴

제뉴어리의 모든것

@EnableJpaAuditing과 @SpringBootApplication 을 같이 쓸때, Test에서 발생되는 에러 본문

BugNote

@EnableJpaAuditing과 @SpringBootApplication 을 같이 쓸때, Test에서 발생되는 에러

제뉴어리맨 2022. 10. 10. 20:17

상황

현재 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

https://velog.io/@mooh2jj/JUnit-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EC%97%90%EB%9F%AC-JPA-metamodel-must-not-be-empty

 

JUnit 테스트 에러 : JPA metamodel must not be empty!

JUnit 테스트코드 중 @WebMvcTest(특정클래스.class)를 붙인 Controller 클래스를 run할 때 생기는 오류이다. 이는 JPA에서도 @EnableJpaAuditing을 추가했는데 @WebMvcTest가 JPA 관련 Bean들을 로드하지 않기 때문에

velog.io