@SpringBootTest 는 어떻게 동작할까? (1)
개요
- 본 시리즈에서는
@SpringBootTest 의 동작 원리를 확인합니다
- 첫번째 편에서는 기본 컴포넌트에 대해 알아봅니다.
사용한 버전
- junit-jupiter: 5.10.3
- spring-boot-test: 3.3.4
- spring-test: 6.1.13
SpringExtension
- 생각해보면 JUnit 테스트를 실행할뿐인데 Spring Application 이 구동이 됩니다. 어떻게 구동이 되는걸까요?
- 테스트가 실행될때,
org.springframework.test.context.junit.jupiter.SpringExtension 가 단계마다 호출되면서 TestContextManager 를 호출합니다. (JUnit Jupiter 기준)
TestContextManager 는 ApplicationContext 의 로딩을 담당합니다. (내부적으로 위임 처리)

- JUnit 에서
SpringExtension#beforeTestClass 호출 (테스트 클래스마다 호출)
- JUnit 에서
SpringExtension#postProcessTestInstance 호출 (모든 테스트마다 호출)
- JUnit 에서
SpringExtension#beforeEach 호출 (모든 테스트마다 호출)
- JUnit 에서
SpringExtension#beforeTestExecution 호출 (모든 테스트마다 호출)
- 테스트 실행
- JUnit 에서
SpringExtension#afterTestExecution 호출 (모든 테스트마다 호출)
- JUnit 에서
SpringExtension#afterEach 호출 (모든 테스트마다 호출)
- JUnit 에서
SpringExtension#afterAll 호출 (테스트 클래스마다 호출)
- 애플리케이션 종료는
java.lang.Runtime#addShutdownHook 을 통해 종료 처리
TestContext \& TestContextManager \& TestExecutionListener

TestContextManager
SpringExtension 에 의해 테스트마다 하나씩 생성됩니다.
TestContextBootstrapper 에게 TestContext 생성을 위임합니다.
TestContext 에게 ApplicationContext 생성을 위임합니다.
- beforeEach, afterEach 와 같은 LifeCycle Callback 발생시,
TestExecutionListener 에게 처리를 위임합니다.
TestContext
CacheAwareContextLoaderDelegate 에게 ApplicationContext 생성을 위임합니다.
CacheAwareContextLoaderDelegate 는 캐싱된 ApplicationContext 가 있으면 해당 컨텍스트를 반환합니다.
- 다양한 요소를 키로 하여
ApplicationContext 를 캐싱합니다.
- 캐싱된
ApplicationContext 가 없다면 SmartContextLoader 에게 위임합니다.
TestExecutionListener
- LifeCycle Callback 발생시,
TestContextManager 에 의해 호출됩니다.
- 대표적인
TestExecutionListener 는 아래와 같습니다. TestExecutionListener Configuration
- DependencyInjectionTestExecutionListener : 테스트 인스턴스에 DI 를 처리합니다 (
@Autowired)
- DirtiesContextTestExecutionListener :
@DirtiesContext 를 처리합니다.
- TransactionalTestExecutionListener :
@Transactional 을 처리합니다.
SpringBootTest 를 실행한다고 했을때, 등록되는 TestExecutionListener 는 아래와 같습니다.
결론
- JUnit 테스트 실행시
SpringExtension 을 통해 애플리케이션이 구동됨을 알아보았습니다.
- 기본 컴포넌트 간의 관계에 대해 알아보면서 어떻게 애플리케이션이 초기화 되고
@Transactional 같은 어노테이션이 동작하는지 알아보았습니다.
- 그러나 Spring Test 와 Spring Boot Test 는 초기화시 구체적인 단계가 다른데요, 이부분은 다음 편에서 알아보겠습니다~
Reference