Testing
The classes in this example show the use of named hierarchy levels in order to merge the configuration for specific levels in a context hierarchy. BaseTests defines two levels in the hierarchy, parent and child. ExtendedTests extends BaseTests and instruct
docs.spring.io
틀린 부분이 있으면 알려주세요 🤲
5. Spring TestContext Framework (1)
5.1. Key Abstractions ~ 5.5. Test Execution Events
5. Spring TestContext Framework
org.springframework.test.context
TestContextFramework 는 사용 중인 테스트 프레임워크에 구애받지 않는 일반 적인 주석 기반 단위 및 통합 테스트를 지원한다
애노테이션을 사용하여 재정의 할 수 있는 기본 값을 사용하여 구성에 대한 규칙을 중시 한다
일반 테스트 인프라 외에도 JUnit 4, JUnit Jupiter(AKA JUnit 5) 및 TestNG에 대한 명시적 지원을 제공한다.
5.1. Key Abstractions
The core of the framework consists of the TestContextManager class and the TestContext, TestExecutionListener, and SmartContextLoader interfaces.
TestContext 프레임워크의 핵심은
TestContextManager클래스와 TestContext, TestExcutionListener 및 SmartContextLoader interface로 구성되어있다
각 테스트에 대해서 TestContextManager 가 생성된다 (JUnit Jupiter의 단일 테스트 클래스 내에서 모든 테스트 메서드 실행)
TestContextManager 는 현재 테스트의 context를 보유하는 TestContext를 관리한다
또한 테스트 진행에 따라 TestContext의 상태를 업데이트하고 Dependency injection(DI), transactions 관리 등을 제공하여 실제 테스트 실행을 계측하는 TestExcutionListener 구현에 위임한다
SmartContextLoader는 주어진 테스트 클래스에 대한 ApplicationContext를 load 한다
org.springframework.test.context (Spring Framework 6.0.4 API)
This package contains the Spring TestContext Framework which provides annotation-driven unit and integration testing support that is agnostic of the actual testing framework in use. The same techniques and annotation-based configuration used in, for exampl
docs.spring.io
5.1.1.TestContext
5.1.2.TestContextManager
TestContextManager는 이 TestContext Framework의 주요 entry point이고 단일 TestContext를 관리하고 잘 정의된 테스트 실행 지점에서 등록된 각 TestExecutionListener 에 signaling events 를 보내는 역할을 한다.
- Prior to any “before class” or “before all” methods of a particular testing framework.
- Test instance post-processing.
- Prior to any “before” or “before each” methods of a particular testing framework.
- Immediately before execution of the test method but after test setup.
- Immediately after execution of the test method but before test tear down.
- After any “after” or “after each” methods of a particular testing framework.
- After any “after class” or “after all” methods of a particular testing framework.
5.1.3.TestExecutionListener
TestExecutionListener는 listener가 등록된 TestContextManager가 게시한 테스트 실행 이벤트에 반응할 수 있도록 API를 정의한다
<5.3 에서 전체적으로 정리가 되어있어 정리 할 예정>
5.1.4. Context Loaders
ContextLoader는 TestContextFramework 에서 통합 테스트를 위해
ApplicationContext를 로드하기 위한 strategy interface이다.
You should implement SmartContextLoader instead of this interface to provide support for component classes, active bean definition profiles, test property sources, context hierarchies, and WebApplicationContext support.
구성요소의 클래스, 활성화된 bean 정의 프로필, test propery sources, context 계층 그리고 WebApplicationContext에 대한 지원을 제공하려면 ContextLoader 대신 SmartContextLoader를 구현해야한다
SmartContextLoader 는 ContextLoader SPI를 최소로 대체하는 ContextLoader interface의 확장이다
특히 리소스 위치, 구성 요소 클래스 또는 context 초기화 프로그램을 처리할 수 있도록 선택이 가능하고
active bean definition profile을 설정하고 로드하는 context에서 속성 소스를 테스트할 수 있다
- DelegatingSmartContextLoader: One of two default loaders, it delegates internally to an AnnotationConfigContextLoader, a GenericXmlContextLoader, or a GenericGroovyXmlContextLoader, depending either on the configuration declared for the test class or on the presence of default locations or default configuration classes. Groovy support is enabled only if Groovy is on the classpath.
- WebDelegatingSmartContextLoader: One of two default loaders, it delegates internally to an AnnotationConfigWebContextLoader, a GenericXmlWebContextLoader, or a GenericGroovyXmlWebContextLoader, depending either on the configuration declared for the test class or on the presence of default locations or default configuration classes. A web ContextLoader is used only if @WebAppConfiguration is present on the test class. Groovy support is enabled only if Groovy is on the classpath.
- AnnotationConfigContextLoader: Loads a standard ApplicationContext from component classes.
- AnnotationConfigWebContextLoader: Loads a WebApplicationContext from component classes.
- GenericGroovyXmlContextLoader: Loads a standard ApplicationContext from resource locations that are either Groovy scripts or XML configuration files.
- GenericGroovyXmlWebContextLoader: Loads a WebApplicationContext from resource locations that are either Groovy scripts or XML configuration files.
- GenericXmlContextLoader: Loads a standard ApplicationContext from XML resource locations.
- GenericXmlWebContextLoader: Loads a WebApplicationContext from XML resource locations.
5.2. Bootstrapping the TestContext Framework
TestContext 또는 ContextCache를 사용자 정의대로 바꾸어 구현하거나, ContextCustomizerFactory, TestExecutionListener default sets 을 augment 할 경우가 있다.
For such low-level control over how the TestContext framework operates, Spring provides a bootstrapping strategy.
이를 위해 bootstrapping strategy 를 제공한다
TestContextBootstrapper defines the SPI for bootstrapping the TestContext framework. A TestContextBootstrapper is used by the TestContextManager to load the TestExecutionListener implementations for the current test and to build the TestContext that it manages. You can configure a custom bootstrapping strategy for a test class (or test class hierarchy) by using @BootstrapWith, either directly or as a meta-annotation. If a bootstrapper is not explicitly configured by using @BootstrapWith, either the DefaultTestContextBootstrapper or the WebTestContextBootstrapper is used, depending on the presence of @WebAppConfiguration.
Since the TestContextBootstrapper SPI is likely to change in the future (to accommodate new requirements), we strongly encourage implementers not to implement this interface directly but rather to extend AbstractTestContextBootstrapper or one of its concrete subclasses instead.
5.3. TestExecutionListener Configuration
Spring provides the following TestExecutionListener implementations that are registered by default, exactly in the following order:
- ServletTestExecutionListener: Configures Servlet API mocks for a WebApplicationContext.
- DirtiesContextBeforeModesTestExecutionListener: Handles the @DirtiesContext annotation for “before” modes.
- ApplicationEventsTestExecutionListener: Provides support for ApplicationEvents.
- DependencyInjectionTestExecutionListener: Provides dependency injection for the test instance.
- DirtiesContextTestExecutionListener: Handles the @DirtiesContext annotation for “after” modes.
- TransactionalTestExecutionListener: Provides transactional test execution with default rollback semantics.
- SqlScriptsTestExecutionListener: Runs SQL scripts configured by using the @Sql annotation.
- EventPublishingTestExecutionListener: Publishes test execution events to the test’s ApplicationContext (see Test Execution Events).
5.3.1. Registering TestExecutionListener Implementations
You can register TestExecutionListener implementations explicitly for a test class, its subclasses, and its nested classes by using the @TestExecutionListeners annotation. See annotation support and the javadoc for @TestExecutionListeners for details and examples.
// Switch to default listeners
@TestExecutionListeners(
listeners = {},
inheritListeners = false,
mergeMode = MERGE_WITH_DEFAULTS)
class MyTest extends BaseTest {
// class body...
}
5.3.2. Automatic Discovery of Default TestExecutionListener Implementations
@TestExecutionListener 애노테이션을 사용하는 것은 제한된 테스트 시나리오에서 사용되는 사용자 정의에 적합하다
전체 테스트에서 사용자 정의 리스너를 사용할 경우 SpringFactoriesLoader 의 기본 구현 자동검색 지원이 가능하다
특히 sprint-test 모듈은 META-INF/spring.factoires 속성 파일의 org.springframework.test.context.TestExecutionListener 키에서 모든 핵심 기본 TestExecutionListener 구현을 선언한다
자체 META-INF/spring.factoires 가 있더라도 동일한 방식으로 기본 listener list에 자체 TestExecutionListener 구현을 제공할 수 있다
5.3.3. Ordering TestExecutionListener Implementations
SpringFactoriesLoader mechanism 을 통해 기본 TestExecutionListener 구현을 발견하면 instance화 된 리스너는 Spring’s Ordered interface and @Order annotation for ordering 의 AnnotationAwareOrderComparator을 사용하여 정렬된다
Spring에서 제공하는 AbstractTestExecutionListener 및 all default TestExecutionListener 구현은 적절한 값으로 정렬되어 구현된다
Ordered를 구현하거나 @Order 를 선언하여 기본 TestExecutionListener 구현이 올바른 순서로 등록되었는지 확인해야한다
각 core listener에 할당되는 값에 대한 자세한 내용은 core 기본 구현 메소드를 참조해보자
5.3.4. Merging TestExecutionListener Implementations
사용자 정의된 @TestExecutionListeners 를 등록하면 기본 리스너가 등록되지 않는다
@ContextConfiguration
@TestExecutionListeners({
MyCustomTestExecutionListener.class,
ServletTestExecutionListener.class,
DirtiesContextBeforeModesTestExecutionListener.class,
DependencyInjectionTestExecutionListener.class,
DirtiesContextTestExecutionListener.class,
TransactionalTestExecutionListener.class,
SqlScriptsTestExecutionListener.class
})
class MyTest {
// class body...
}
The challenge with this approach is that it requires that the developer know exactly which listeners are registered by default. Moreover, the set of default listeners can change from release to release — for example, SqlScriptsTestExecutionListener was introduced in Spring Framework 4.1, and DirtiesContextBeforeModesTestExecutionListener was introduced in Spring Framework 4.2. Furthermore, third-party frameworks like Spring Boot and Spring Security register their own default TestExecutionListener implementations by using the aforementioned automatic discovery mechanism.
Testing
The classes in this example show the use of named hierarchy levels in order to merge the configuration for specific levels in a context hierarchy. BaseTests defines two levels in the hierarchy, parent and child. ExtendedTests extends BaseTests and instruct
docs.spring.io
모든 기본 리스너를 인식하고 다시 선언하지 않으려면 @TestExecutionListeners의 mergeMode 속성을 MergeMode.MERGE_WITH_DEFAULTS로 설정할 수 있다.
MERGE_WITH_DEFAULTS는 로컬로 선언된 리스너가 기본 리스너와 병합되어야 함을 나타낸다.
병합 알고리즘은 목록에서 중복 항목을 제거하고 TestExecutionListener 구현 주문에 설명된 대로 병합된 리스너의 결과 집합이 AnnotationAwareOrderComparator의 의미 체계에 따라 정렬되도록 한다.
리스너가 Ordered를 구현하거나 @Order로 주석이 달린 경우 기본값과 병합되는 위치에 영향을 줄 수 있다.
그렇지 않으면 로컬로 선언된 리스너가 병합될 때 기본 리스너 목록에 추가된다.
MyCustomTestExecutionListener 클래스가 해당 순서 값(예: 500)을 ServletTestExecutionListener의 순서(1000이 됨)보다 작게 구성하면 MyCustomTestExecutionListener가 기본값 목록과 자동으로 병합될 수 있다.
ServletTestExecutionListener 앞에 있으며 다음으로 대체될 수 있습니다.
@ContextConfiguration
@TestExecutionListeners(
listeners = MyCustomTestExecutionListener.class,
mergeMode = MERGE_WITH_DEFAULTS
)
class MyTest {
// class body...
}
5.4. Application Events
Spring Framework 5.3.3 부터 TestContext framework 는 ApplicationContext에 게시된 애플리케이션 이벤트 기록을 지원한다.
테스트 내에 해당 이벤트에 대한 assertions 가 수행될 수 있다.
단일 테스트 실행 중에 게시된 이벤트를 ApplicationEvents API를 통하여 stream으로 처리할 수 있다.
- Ensure that your test class is annotated or meta-annotated with @RecordApplicationEvents.
- Ensure that the ApplicationEventsTestExecutionListener is registered. Note, however, that ApplicationEventsTestExecutionListener is registered by default and only needs to be manually registered if you have custom configuration via @TestExecutionListeners that does not include the default listeners.
- Annotate a field of type ApplicationEvents with @Autowired and use that instance of ApplicationEvents in your test and lifecycle methods (such as @BeforeEach and @AfterEach methods in JUnit Jupiter).
-
- When using the SpringExtension for JUnit Jupiter, you may declare a method parameter of type ApplicationEvents in a test or lifecycle method as an alternative to an @Autowired field in the test class.
테스트 클래스에 @RecordApplicationEvents 주석을 달아준다
ApplicationEventsTestExecutionListener 등록을 확인한다. (기본 리스너에는 포함되어있다, @TestExecutionListeners 를 사용할 경우 수동 등록)
@Autowired로 ApplicationEvents 유형의 필드에 주석을 달고 테스트 및 수명 주기 메서드(@BeforeEach, @AfterEach)에서 해당 ApplicationEvents instance를 사용한다
JUnit Jupiter용 SpringExtension을 사용하는 경우 테스트 클래스의 @Autowired 필드 대신 테스트 또는 수명 주기 메서드에서 ApplicationEvents 유형의 메서드 매개변수를 선언할 수 있다.
@SpringJUnitConfig(/* ... */)
@RecordApplicationEvents
class OrderServiceTests {
@Autowired
OrderService orderService;
@Autowired
ApplicationEvents events;
@Test
void submitOrder() {
// Invoke method in OrderService that publishes an event
orderService.submitOrder(new Order(/* ... */));
// Verify that an OrderSubmitted event was published
long numEvents = events.stream(OrderSubmitted.class).count();
assertThat(numEvents).isEqualTo(1);
}
}
테스트 클래스에 @RecordApplicationEvents 달았고
ApplicationEvents 에 @Autowired
5.5. Test Execution Events
EventPublishingTestExecutionListener는 사용자 정의 TestExecutionListener 구현에 대한 대체 접근 방식을 제공한다.
테스트의 ApplicationContext에 있는 구성요소는 TestExecutionListener API의 메서드에 해당하는 EventPublishingTestExecutionListener에서 게시하고 이벤트를 수신 대기할 수 있다
- BeforeTestClassEvent
- PrepareTestInstanceEvent
- BeforeTestMethodEvent
- BeforeTestExecutionEvent
- AfterTestExecutionEvent
- AfterTestMethodEvent
- AfterTestClassEvent
이를 사용할 수 있도록 하는는 애노테이션 org.springframework.test.context.event.annotation
- @BeforeTestClass
- @PrepareTestInstance
- @BeforeTestMethod
- @BeforeTestExecution
- @AfterTestExecution
- @AfterTestMethod
- @AfterTestClass
5.5.1. Exception Handling
기본적으로 테스트 실행 이벤트 리스너가 이벤트를 소비하는 동안 예외를 발생시키면 해당 예외는 사용 중인 기본 테스트 프레임워크(예: JUnit 또는 TestNG)로 전파된다.
예를 들어, BeforeTestMethodEvent의 소비로 인해 예외가 발생하면 해당 테스트 메서드는 예외의 결과로 실패한다.
반대로 비동기 테스트 실행 이벤트 리스너가 예외를 발생시키는 경우 예외는 기본 테스트 프레임워크로 전파되지 않는다.
5.5.2. Asynchronous Listeners
If you want a particular test execution event listener to process events asynchronously, you can use Spring’s regular @Async support. For further details, consult the class-level javadoc for @EventListener.
'Web > spring' 카테고리의 다른 글
[Spring framework Web MVC docs] 1.1.6.Path Matching ~ 1.1.7. Interception (0) | 2023.02.10 |
---|---|
[Spring framework testing] 5. Spring TestContext Framework (2) (0) | 2023.02.09 |
[Spring security] Architecture (0) | 2023.02.08 |
[Spring framework Web MVC docs] 1.1.1.Context Hierarchy ~ 1.1.5. Processing (0) | 2023.02.08 |
[Spring framework Web MVC docs] 1.1.8. Exceptions (0) | 2023.02.06 |