[Spring Test] Spring TestContext Framework
Prolog
스프링 4독을 앞두고 있다. 3독까지 해보니까 레퍼런스 전체적으로 자주 나오는 몇가지 키워드가 있다는 걸 알게되었다. 그래서 많이 등장하는 키워드를 한번 다 적어보았다.
그리고 실제 테스트를 돌려보았다. 많이 보았던 키워드들이 정말 많이 등장했다. 뭔진 모르겠지만 내가 앞으로 레퍼런스를 읽을 때 도움이 되겠구나.
All above listeners have a specific responsibility in Spring integration tests execution. For example, DependencyInjectionTestExecutionListener provides support for dependency injection and initialization of test instances.
예를들면 테스트에서의 DependencyInjection 에 대한 부분에서 TestExecutionListener 라는 키워드가 나오고 DirtiesContext 에 대한 부분에서도 TestExecutionListener 라는 키워드가 나왔.다. 도대체 TestExecutionListener 라는 키워드가 뭔데? 근데 또 하필 가장 많이 등장하는 키워드 두 개 (TestContext, TestExecutionListener) 가 Spring TestContext Framework 에 속한다. 사실 여기서 이름만 보더라도 중요한 역할을 하는 애들이구나 눈치챌 수 있었다.
Today’s Study Topic
Spring TestContext Framework
Notes
📌 TestExecutionListener
TestExecutionListener defines a listener API for reacting to test execution events published by the TestContextManager with which the listener is registered.
📌 TestContextManager
TestContextManager is the main entry point into the Spring TestContext Framework.
- getTestContext() 메서드가 호출되면 실행되는 스레드에 TestContext 생성
- TestContextManager 는 내부적으로 TestExecutionListener 를 가져온다. List<TestExecutionListener> 에 하나씩 넣고, 테스트 클래스 실행 전과 후, 테스트 메소드 실행 전과 후, 등록된 리스너들을 관리한다. handleBeforeException를을 통해 exception도 핸들링 하는 것 같이 보인다.
📌 DefaultTestContext implements TestContext
TestContext encapsulates the context in which a test is executed, agnostic of the actual testing framework in use.
→ / TestClass / TestMethod .. 등 테스트에 관련된 모든 정보가 있다.
→ cacheAwareContextLoaderDelegate.loadContext 을 통해 ApplicationContext가 생성된다!
- 테스트를 실행하면 @Test 어노테이션은 클래스 어노테이션(@SpringBootTest)을 확인하고 테스트 프레임워크의 TestContextManager를 호출한다.
- TestContextManager 는 Test Pool을 전반적으로 관리하는 TestContext 를 띄우고 , 이 컨텍스트는 실제 ApplicationContext를 띄우기 위해 ContextLoader 에 위임한다.
- ApplicationContext가 완성되면, TestExecutionListener 가 JUnit 생명주기에 맞춰 트랜잭션도 관리하면서, 테스트를 실행하게 된다.
📍 내가 알게된 것 !
- 테스트에서 스프링 빈을 사용하기 위해서는 ApplicationContext를 띄워야 한다. (→ 스프링 부트 설정을 통해 자동으로 Spring TestContext Framework를 사용하게 되어있다)
- 테스트 프레임워크는 TextContext안에 ApplicationContext가 만든다.
- 테스트 프레임워크를 이루는 핵심 요소는 TestContextManager, TestContext, TestExecutionListener 이다.
- Spring Test에서 어플리케이션 컨텍스트는 딱 한 개만 만들어지고 모든 테스트에서 공유해서 사용한다. 따라서 어플리케이션 컨텍스트의 구성이나 상태를 테스트 내에서 변경하지 않는 것이 원칙이다. 만약 변경해야 한다면 @DirtiesContext 어노테이션을 붙이면 어플리케이션 컨텍스트를 공유하지 않는다.
많은 TestExecutionListner 중에 한 가지만 살펴보자.
public class MockitoTestExecutionListener
스프링 테스트에서 사용되는 Mock 을 생성해주고 있다...!
Relevant Question
📌 Question
- TestExecutionListeners 는 모든 테스트에 적용되는 걸까?
- 그럼 mock객체가 필요없는 테스트에 MockitoTestExecutionListener 가 돌아가나? 디폴트가 그렇게 되어있는걸까?
- 스프링 테스트 동작원리에 숨어있는 일정한 패턴들은 뭐가있을까.
- TestContextManager 내부에서 발견한 TestContextBootstrapper 는 어떤 역할을 하는 걸까.
+) TestContextManager 내부에서 발견한 TestContextBootstrapper ?
실제로 테스트를 실행하면, textcontextBootstrapper가 호출되고 이는 테스트 프레임워크를 쉽게 실행시켜준다.
TestContextBootstrapper는 TestContextManager에서 현재 테스트에 대한 TestExecutionListeners를 가져오고 관리하는 TestContext를 빌드하는 데 사용됩니다.
+) 관련있는 것 같은데 뭔지 모르겠는 SpringExtension
Relevant Reference
- https://github.com/spring-projects/spring-framework/blob/main/spring-test/src/main/java/org/springframework/test/context/TestExecutionListener.java
- https://www.logicbig.com/tutorials/spring-framework/spring-core/test-execution-listener.html
- https://www.concretepage.com/spring-5/testexecutionlisteners-example-spring-test