멀티 모듈(헥사고날 아키텍쳐)환경에서
JPA 레포지토리 테스트를 작성하다 만난 에러를 고친 과정을 정리한 글입니다.
멀티 모듈 프로젝트에서 JPA 레포지토리 인터페이스에 메서드를 작성하고 테스트를 하려는데
레포지토리 코드가 빈으로 등록되지 않는 에러에 직면했다.
이게 뭔가 싶어 열심히 구글링을 해본 결과 관련 내용을 잘 정리한 블로그가 있었다.
출처 : https://devlog-wjdrbs96.tistory.com/433
즉, 멀티 모듈 프로젝트는
전체 스프링 프로젝트의 시작점인Application
파일을 특정 모듈에 넣어놓고 애플리케이션을 실행하는데
Application
파일이 없는 모듈의 경우 관련 파일이 없어서 빈으로 등록되지 않는 것 이었다.
이를 해결하기 위해 테스트하고자 하는 모듈의 test 패키지에
스프링 애플리케이션을 구동하고 빈으로 등록하기 위한 설정파일을 추가했다.
그 이후 설정한 파일을 @ContextConfiguration
에너테이션을 통해 읽어오는 작업을 해주었다.
설정 파일을 추가하고 이번에는 성공하겠지 하는 부푼마음을 앉고 테스트 실행을 했으나 다른 에러에 직면한다.
java.lang.IllegalStateException: Failed to load ApplicationContext
... 생략
Caused by: org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'jwtTokenProvider':
Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException:
Could not resolve placeholder 'jwt.issuer' in value "${jwt.issuer}”
...
그것은 바로.. 도메인 모듈에 있는 jwtTokenProvider
빈 생성에 실패했다는 에러였다.
JPA 모듈을 테스트하고 있는데 갑자기 왜 뜬금없이 도메인 모듈에서 말썽이란 말인가??
몇시간의 고된 삽질 결과 문제의 상황은 이렇다.
다시 레포지토리 테스트 코드를 유심히 보면
@SpringBootTest
@SpringBootTest
요놈이 문제의 원흉이었다.
그것은 바로, 스프링과 같은 환경에서 실행하기 위해 빈을 생성해서 테스트 환경을 실행해주기 때문이다.
현재 내 프로젝트는 헥사고날 아키텍쳐의 구조이다.
헥사고날 아키텍쳐 에서는 도메인 모듈의 의존성을 외부 (컨트롤러, 디비, 외부 api와 통신 등등)의 역할을 하는 모듈이 가지고 있는 형태를 띄게 되는데,
내 프로젝트에서도 JPA 모듈에서 도메인 모듈의 의존성을 가지고 있다.
이것과 @SpringBootTest
가 어우려져서 환장할 에러를 만들어냈다.
스프링 환경과 동일하게 빈을 생성하려다 보니 의존성을 가지고 있는 CORE 모듈
의 클래스들도 빈으로 생성했던 것이다.
하지만, CORE 모듈
의 설정파일은 JPA 모듈
에서 알 턱이 없다.
그래서 jwtTokenProvider
가 필요한 설정을 읽지 못해 빈 등록에 실패하고 테스트를 하지 못한것이었다.
스프링 공식 가이드 문서에 보면 다음과 같이 적혀있다.
@DataJpaTest
에너테이션이 사용될 때 일반@Component
및@ConfigurationProperties
빈은 스캔되지 않습니다.
@EnableConfigurationProperties
는@ConfigurationProperties
빈을 포함하는 데 사용할 수 있습니다.
@DataJpaTest
을 사용하면 @SpringBootTest
과는 달리 빈을 다 등록하지 않고 JPA 환경에 필요한 것들만 가지고 테스트를 한다는 등의 내용인 듯 하다.
에너테이션을 바꿔주니 바로 보이는 초록불 😃
테스트는 성공했지만 제대로 된 테스트 환경을 설정하려면
필요한 설정파일을 읽는 에너테이션들이 추가로 필요하다.
이런 에너테이션들을 매번 테스트 코드에 덕지덕지 달아주는 것은 생각만 해도 끔찍하다. 🤮
이를 해결하기 위해 커스텀 에너테이션을 따로 만들어서 테스트에 필요한 공통 설정파일을 모아놓고 관리하기로 했다.
이제 귀찮은 테스트 설정은 저 에너테이션에서 관리하고 사용하기만 하면 된다! 야호 😃
@SpringBootTest
와 @DataJpaTest
에너테이션의 차이를 알게 되었고,
멀티 모듈이라는 특수한 환경에서 @SpringBootTest
를 잘못 쓰면 엉뚱한 빈들까지 다 끌고 오는것을 알았다.
음.. 마치 JPA의 연관관계 즉시 로딩 설정으로 연관된 객체를 다 끌고오는것 같은 느낌이다.. 😂
테스트 하고자 하는 환경에 맞게 설정을 결정하는것이 중요한 것 같다.
그리고 역시 상상 코딩과 현실 코딩은 많이 다른것 같다… 😅