문제 상황
SpringBoot의 Junit5에서 Memory DB를 사용하여 Repository 계층을 테스트하는 방법은 크게 두가지가 있습니다.
1. @DataJpaTest 활용
2. @SpringBootTest + MemoryDB
이중 @DataJpaTest를 활용하여 Repository계층을 테스트하는 상황에서 만난 오류를 정리해보려고 합니다.
오류의 내용은 MEMBER라는 테이블을 찾을 수 없어 sql 쿼리를 준비할 수 없다는 내용이었습니다.
분명 application-test.yml 파일은 다음과 같이 ddl-auto를 create로 설정하여 테이블을 생성하도록 하였고
@ActiveProfiles("test") 어노테이션을 사용하여 해당 설정파일을 읽도록 하였습니다.
도무지 이해할 수 없는 에러였습니다.
로그 확인하기
로그를 확인해보니 데이터베이스 접속 정보가 다르다는 것을 발견했습니다.
설정: jdbc:h2:mem:test
로그: jdbc:h2:mem:1e8b29d6-d98f-46c3-b8dd-e2c96210d60e;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false
내가 한 설정들이 현재 적용되고 있지 않다는 것을 알게되었습니다.
@DataJpaTest?
먼저 @DataJpaTest는 Spring Boot에서 JPA와 관련된 기능을 테스트하기 위해 제공하는 테스트 전용 애너테이션 입니다.
주로 레포지토리 계층을 테스트할 때 사용되며, 테스트 환경에서만 필요한 최소한의 설정만 로드하여
빠르고 효율적인 단위 테스트를 진행하기 위해 사용합니다.
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@BootstrapWith(DataJpaTestContextBootstrapper.class)
@ExtendWith({SpringExtension.class})
@OverrideAutoConfiguration(
enabled = false
)
@TypeExcludeFilters({DataJpaTypeExcludeFilter.class})
@Transactional
@AutoConfigureCache
@AutoConfigureDataJpa
@AutoConfigureTestDatabase
@AutoConfigureTestEntityManager
@ImportAutoConfiguration
public @interface DataJpaTest {
...
}
@DataJpaTest에는 몇가지 특징이 있습니다.
1. @Transactional
@DataJpaTest는 내부적으로 @Transactional을 사용하고 있기 때문에 SELECT를 제외한 모든 쿼리는 롤백 대상입니다.
즉, 영속성 컨텍스트의 flush()가 실행되어야 쿼리가 발생하는 구조에서
애초에 롤백 대상인것들은 쿼리가 실행되지 않을 수 있습니다.
다만 Entity를 영속성 컨텍스트에 담기위해서는 기본키가 결정되어야 하고
기본키 전략이 GenerationType.IDENTITY인 경우 DB에 데이터가 INSERT된 이후 결정되기 때문에
save()메서드가 실행된 이후 insert query가 실행되는 것을 확인할 수 있습니다.
2. @AutoConfigureTestDatabase
@AutoConfigureTestDatabase는 별도의 설정없이 테스트를 위한 내장 데이터베이스(H2)를 사용합니다.
기본값은 Replace.ANY로 실제 데이터베이스 설정이 있더라도 내장 데이터베이스로 대체하는 것을 의미합니다.
해결방법
@DataJpaTest
@ActiveProfiles("test")
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
class MemberRepositoryTest {
- @DataJpaTest 어노테이션으로 테스트를 수행하면 yml 파일에 정의된 데이터베이스 설정을 사용하지 못합니다.
- 이유는 @AutoConfigureTestDatabase 어노테이션이 기본값으로 테스트를 위한 내장 데이터베이스로 대체해버리기 때문입니다.
- 다음과 같이 AutoConfigureTestDatabase에 replace의 속성값을 NONE으로 설정하게 되면 정상적으로 yml파일의 설정을 사용합니다.
'Java > JPA' 카테고리의 다른 글
JPA Hibernate의 프록시와 일대일 관계에서의 N+1 문제 (0) | 2024.10.06 |
---|---|
AWS 프리티어 환경에서 데이터 20만건 조회하기 (0) | 2024.09.22 |
JPA 복잡한 쿼리 작성하기 (0) | 2024.09.20 |