[JPA] `@SpringApplication` 없는 모듈에서 `@DataJpaTest` 사용하기

가영·2022년 8월 13일
0

기록하기 위한 글이라 설명이 친절하지 않을 수 있습니다.


나는 core 모듈에 도메인 엔티티와 리포지토리, 서비스를 만들고 있다
근데 application 클래스를 rest 모듈에 가지고 있었다.
나는 jpa 리포지토리를 사용하기 때문에 구현체를 내가 만들 수 없었고 (mocking 말고 실제 리포지토리)
그래서 그동안 리포지토리를 테스트 클래스에 DI 하고 싶으면 rest 모듈에서 했어야했다.

  • core/test 에서 테스트를 만들 경우 - autowire가 불가능했음

그리고 나서 확인하고 싶은 것이 확인되면 테스트 클래스를 삭제하고는 했다. 여기(core모듈에) 있으면 안 될 것 같아서.

그런데 이제 그렇게 하기 싫었다. 테스트를 만드는 그 때보다는, 새로운 기능들을 만들며 계속 테스트를 돌리는 데에 의의가 굉장히 크다고 생각하기 때문에 저장을 하고 싶었고, 그래서 core 모듈에서 di를 할 방법을 찾기 시작했다.

@SpringApplication

처음엔 그냥 내가 테스트하는 클래스에 @SpringBootApplication을 붙였다. (개무식)

그리고 테스트를 실행해보았다.
테스트가 정상동작하지 않았고, 예외는 다음과 같았다.

in-memory db를 안써서요

org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'dataSourceScriptDatabaseInitializer' defined in class path resource [org/springframework/boot/autoconfigure/sql/init/DataSourceInitializationConfiguration.class]: Unsatisfied dependency expressed through method 'dataSourceScriptDatabaseInitializer' parameter 0;

Caused by: org.springframework.beans.factory.BeanCreationException: 
Error creating bean with name 'dataSource': Invocation of init method failed

Caused by: java.lang.IllegalStateException: Failed to replace DataSource with an embedded database for tests. 
If you want an embedded database please put a supported one on the classpath or tune the replace attribute of @AutoConfigureTestDatabase.

@DataJpaTest 문서를 보면 다음과 같이 설명돼있다.

By default, tests annotated with @DataJpaTest are transactional and roll back at the end of each test. They also use an embedded in-memory database (replacing any explicit or usually auto-configured DataSource). The @AutoConfigureTestDatabase annotation can be used to override these settings.

자동으로 embedded in-memory db를 사용한다는 것이다. 나는

선생님께서는 이렇게 하라고 하셨다.

@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)

테스트 db를 사용하지 않도록 설정을 해주고 다시 돌려봅시다.

아 맞다 컴포넌트 스캔

(대충 기록만..)

Error creating bean with name 'entityManagerFactory'
...
Caused by: org.hibernate.AnnotationException: @OneToOne or @ManyToOne 
on com.zoin.rendezvous.domain.notification.FriendNotification.friendRelationship references an unknown entity: com.zoin.rendezvous.domain.friend.Friend

아무튼 FriendNotification 엔티티가 참조하는 Friend 엔티티를 못찾는다는 얘기다.

이유는 @SpringBootApplication이 붙은 클래스(FriendNotificationTest)의 위치때문이다.

마찬가지로 문서를 보면, @SpringBootApplication 은 `@ComponentScan라는 어노테이션을 포함하고 있고, base package의 default 값이 해당 클래스가 속한 패키지가 된다고 써있다.

후 이걸 까먹따니. 이거 베이스 패키지 어노테이션으로 설정해줄 바에는 전역으로 쓸 수 있게 test base 패키지에 클래스하나 만드는게 낫겠다는 판단을 했다. 그래서 다음처럼 추가해줬더니 잘 돌아간다.

오예

+) 외에도 Kotest 에서 EntityManager가 정상 동작하게 하려면 kotest의 spring extension을 사용해야 한다.

참고

[Kotlin] Kotest 시 EntityManager가 정상동작 하지 않는 현상 기록

0개의 댓글