@TestExecutionListeners in Spring Test
November 25, 2019
The Spring @TestExecutionListeners
is a class level annotation that configures custom TestExecutionListener
listeners to be registered with TestContextManager
. The TestContextManager
is the main entry point into the Spring test context framework. To create custom TestExecutionListener
, we need to create a class by implementing TestExecutionListener
interface. The @TestExecutionListeners
annotation is used in conjunction with @ContextConfiguration
.
@TestExecutionListeners Annotation
The
@TestExecutionListeners
annotation has following optional elements.
inheritListeners: In a test class hierarchy, the
inheritListeners
element defines whether or not TestExecutionListener
from the super class should be inherited. Default value is true.
mergeMode: The
mergeMode
element is effective only when the test class is not inheriting listeners from the super class. The value of mergeMode
can be MERGE_WITH_DEFAULTS
and REPLACE_DEFAULTS
. In MERGE_WITH_DEFAULTS
locally declared listeners are merged with the default listeners. In REPLACE_DEFAULTS
locally declared listeners replace the default listeners and this is default.
listeners: Registers implementations of
TestExecutionListener
interface.
value: Alias of
listeners
element.TestExecutionListener Interface
The
TestExecutionListener
interface provides following default
methods that can be overridden in our custom class.
beforeTestClass: Executes before execution of all tests within the class.
prepareTestInstance: Prepares test instances such as injecting dependencies.
beforeTestMethod: Executes before execution of before lifecycle of each test method.
beforeTestExecution: Executes immediately before execution of test method.
afterTestExecution: Executes immediately after execution of test method.
afterTestMethod: Executes after execution of after lifecycle of each test method.
afterTestClass: Executes after execution of all tests within the class.
Spring provides built-in implementations of
TestExecutionListener
interface such as ServletTestExecutionListener
, DirtiesContextTestExecutionListener
, TransactionalTestExecutionListener
, DependencyInjectionTestExecutionListener
etc. We can use them as following.
@ExtendWith(SpringExtension.class) @ContextConfiguration @TestExecutionListeners({ DependencyInjectionTestExecutionListener.class, DirtiesContextTestExecutionListener.class }) public class MyAppTest { ...... }
TestExecutionListener
interface and configure them using @TestExecutionListeners
annotation in our integration test class.
Technologies Used
Find the technologies being used in our example.1. Java 11
2. Spring 5.2.0.RELEASE
3. Spring Boot 2.2.0.RELEASE
4. JUnit 5.3.2
5. Maven 3.5.2
6. Eclipse 2018-09
Maven Dependencies
Find the Maven dependencies.pom.xml
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.0.RELEASE</version> <relativePath/> </parent> <properties> <java.version>11</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <version>5.3.2</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <version>5.3.2</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-params</artifactId> <version>5.3.2</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.platform</groupId> <artifactId>junit-platform-launcher</artifactId> <version>1.3.2</version> <scope>test</scope> </dependency> <dependency> <groupId>org.hsqldb</groupId> <artifactId>hsqldb</artifactId> <version>2.5.0</version> <scope>test</scope> </dependency> </dependencies>
Complete Example
Find the custom implementations ofTestExecutionListener
interface.
MyTestExecutionListener
package com.concretepage; import org.springframework.test.context.TestContext; import org.springframework.test.context.TestExecutionListener; public class MyTestExecutionListener implements TestExecutionListener { public void beforeTestClass(TestContext testContext) throws Exception { System.out.println("--- beforeTestClass ---"); } public void prepareTestInstance(TestContext testContext) throws Exception { System.out.println("--- prepareTestInstance ---"); } public void beforeTestMethod(TestContext testContext) throws Exception { System.out.println("--- beforeTestMethod ---"); } public void beforeTestExecution(TestContext testContext) throws Exception { System.out.println("--- beforeTestExecution ---"); } public void afterTestExecution(TestContext testContext) throws Exception { System.out.println("--- afterTestExecution ---"); } public void afterTestMethod(TestContext testContext) throws Exception { System.out.println("--- afterTestMethod ---"); } public void afterTestClass(TestContext testContext) throws Exception { System.out.println("--- afterTestClass ---"); } }
MyAppTest.java
package com.concretepage; import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInfo; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.TestExecutionListeners; import org.springframework.test.context.TestExecutionListeners.MergeMode; import org.springframework.test.context.junit.jupiter.SpringExtension; @ExtendWith(SpringExtension.class) @ContextConfiguration @TestExecutionListeners(listeners = { MyTestExecutionListener.class }, mergeMode = MergeMode.MERGE_WITH_DEFAULTS) public class MyAppTest { @BeforeAll static void initAll() { System.out.println("---@BeforeAll: Inside initAll---"); } @BeforeEach void init(TestInfo testInfo) { System.out.println("---@BeforeEach: Inside init--- test: " + testInfo.getDisplayName()); } @Test public void testMethod1() { assertEquals(true, 30 > 20); } @Test public void testMethod2() { assertEquals(true, 10 < 15); } @AfterEach void tearDown(TestInfo testInfo) { System.out.println("---@AfterEach: Inside tearDown---"); } @AfterAll static void tearDownAll() { System.out.println("---@AfterAll: Inside tearDownAll---"); } }
--- beforeTestClass --- ---@BeforeAll: Inside initAll--- --- prepareTestInstance --- --- beforeTestMethod --- ---@BeforeEach: Inside init--- test: testMethod1() --- beforeTestExecution --- --- afterTestExecution --- ---@AfterEach: Inside tearDown--- --- afterTestMethod --- --- prepareTestInstance --- --- beforeTestMethod --- ---@BeforeEach: Inside init--- test: testMethod2() --- beforeTestExecution --- --- afterTestExecution --- ---@AfterEach: Inside tearDown--- --- afterTestMethod --- ---@AfterAll: Inside tearDownAll--- --- afterTestClass ---
References
Spring testing: @TestExecutionListenersAnnotation Type TestExecutionListeners
Interface TestExecutionListener