@JdbcTest와 @DataJdbcTest
테스트를 작성함에 있어, 중요한 요소 중 하나는 빠르게 수행되어야 한다는 것이다. (테스트 수행 시간이 길어진다면, 코드를 수정하고 테스트하는 작업을 안 하게 될 수 있다.)
그래서 나는 Persistence Layer 계층의 클래스들을 테스트할 때 @DataJdbcTest, @JdbcTest를 사용하고 있었다. 하지만 해당 어노테이션들의 의미를 정확히 모르고 사용하고 있었다. 그래서 이번 기회에 공부하고 공부한 내용을 공유하고 싶어 글을 작성하게 됐다.
@JdbcTest
공식 문서를 살펴보면 다음과 같이 정리할 수 있다.
- 모든 스프링 빈을 auto-configuration 하지 않고, JDBC 테스트와 관련된 빈들만 auto-configuration 한다.
- 기본값으로 각각의 테스트는 하나의 트랜잭션이고, 테스트가 끝나면 roll back 된다.
- 기본값으로 in-memory db를 사용한다.
그럼 코드를 통해 어떻게 위에서 말한 것들이 가능해지는 살펴보겠다.
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@BootstrapWith(JdbcTestContextBootstrapper.class)
@ExtendWith(SpringExtension.class)
@OverrideAutoConfiguration(enabled = false) //*
@TypeExcludeFilters(JdbcTypeExcludeFilter.class)
@Transactional //*
@AutoConfigureCache
@AutoConfigureJdbc //*
@AutoConfigureTestDatabase //*
@ImportAutoConfiguration //*
public @interface JdbcTest {
...
}
어떻게 특정 빈들만 SpringContext에 등록될까?
@OverrideAutoConfiuration을 들어가면 다음과 같이 나와있다.
Annotation that can be used to override {@link EnableAutoConfiguration @EnableAutoConfiguration}. Often used in combination with {@link ImportAutoConfiguration @ImportAutoConfiguration} to limit the auto-configuration classes that are loaded.
즉, @OverrideAutoConfiguration과 @ImportAutoConfiguration 어노테이션의 조합으로 현재 내 프로젝트의 모든 빈들을 auto-configuration 하는 게 아니라, 특정 빈만 auto-configuration이 가능하도록 해준다.
@AutoConfigureJdbc를 통해 Jdbc 관련된 빈들만 Spring Context에 등록된다. 이로 인해 위에서 말한 모든 빈들을 등록하는 게 아니라 Jdbc와 관련된 빈들만 등록된다.
어떻게 test마다 Trasnaciton이 적용되고, roll back 될 수 있을까?
@Transactional 어노테이션이 각각의 테스트를 하나의 트랜젝션으로 관리되게 해주고, 테스트가 끝나면 roll back 시켜준다.
어떻게 Test시 in-memory db를 사용할 수 있을까?
@AutoConfigureTestDatabase를 보면 다음과 같이 나와있다.
Annotation that can be applied to a test class to configure a test database to use instead of the application-defined or auto-configured {@link DataSource}. In the case of multiple {@code DataSource} beans, only the {@link Primary @Primary} {@code DataSource} is considered.
즉, 해당 어노테이션이 기본적으로 in-memory db를 사용하는 것을 가능하게 해준다. 만약 다른 테스트에서 다른 db를 사용하고 싶으면 해당 어노테이션을 활용하면 될 것이다.
@DataJdbcTest
@DataJdbcTest는 @JdbcTest와 무슨 차이가 있을까?
공식 문서를 살펴보면, @JdbcTest와 거의 비슷하다. 하지만 다른 점이 하나 있다.
@JdbcTest는 Jdbc 테스트와 관련된 설정들만 auto-configuration 한다고 나와있다. 하지만 @DataJdbcTest의 경우는 Data Jdbc 테스트와 관련된 설정들만 auto-configuration 한다고 나와있다.
이 말로는 명확한 차이를 모르겠다. 코드를 살펴보자.
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@BootstrapWith(DataJdbcTestContextBootstrapper.class)
@ExtendWith(SpringExtension.class)
@OverrideAutoConfiguration(enabled = false)
@TypeExcludeFilters(DataJdbcTypeExcludeFilter.class)
@Transactional
@AutoConfigureCache
@AutoConfigureDataJdbc //*
@AutoConfigureTestDatabase
@ImportAutoConfiguration
public @interface DataJdbcTest {
...
}
@JdbcTest와의 차이점은 @AutoConfigureDataJdbc이다. 왜 공식문에서 다르게 말했는지 알 것 같다.
그럼 Jdbc와 DataJdbc의 차이점이 뭘까?
좀 더 정확하게 말하면 spring-jdbc와 spring-data-jdbc의 차이라고 생각해도 된다.
spring-jdbc는 기존의 plain jdbc를 스프링 프레임워크에서 사용할 수 있도록 추상화한 것이다. 그 예로 @Transactional, JdbcTemplate 모듈이 있다.
반면에 spring-data-jdbc는 spring-jdbc를 추상화한 것이다. 이로 인해 Spring Data CrudRepository를 사용할 수 있다.
정리
@JdbcTest, @DataJdbcTest의 차이는 테스트 시 spring-jdbc 관련 빈들을 등록할지, spring-data-jdbc 관련 빈들을 등록할지의 차이다.
나머지 공통점으로는 테스트에 필요한 빈들만 스프링 컨텍스트에 등록, 기본값으로 in-memory를 사용, 각각의 테스트를 하나의 트랜잭션 단위로 그리고 테스트 후 roll back 해주는 기능을 제공한다.
Persistence layer와 관련된 test를 할 때는 해당 어노테이션을 활용해 더 빠른 테스트를 만들어보자.
Reference
'Spring' 카테고리의 다른 글
Spring's STOMP support 파헤치기 (0) | 2023.06.02 |
---|---|
Spring Websocket Trobleshooting!! (feat. Decorator Pattern) (0) | 2023.05.21 |
Spring Cloud GateWay의 non-blocking server (0) | 2022.12.31 |
@SpringBootTest의 비밀! (0) | 2022.12.11 |
@RequestBody (0) | 2022.06.10 |