Spring provides the following TestExecutionListener
implementations, which
are registered by default, in exactly the following order:
-
ServletTestExecutionListener
: Configures servlet API mock objects for theWebApplicationContext
. -
DirtiesContextBeforeModesTestExecutionListener
: Handles the @DirtiesContext annotation for "before" modes. -
ApplicationEventsTestExecutionListener
: Provides support forApplicationEvents
. -
DependencyInjectionTestExecutionListener
: Provides dependency injection for the test instance. -
DirtiesContextTestExecutionListener
: Handles the @DirtiesContext annotation for after modes. -
TransactionalTestExecutionListener
: Provides transactional execution of tests with default rollback semantics. -
SqlScriptsTestExecutionListener
: Executes SQL scripts configured with the @Sql annotation. -
EventPublishingTestExecutionListener
: Publishes test execution events
inApplicationContext
.
Registering implementations of TestExecutionListener
You can register TestExecutionListener
implementations for a test class and its subclasses using the
@TestExecutionListeners
annotation. For details and examples, see the annotation support subsection and
the annotation javadoc @TestExecutionListeners
.
Automatic detection of default TestExecutionListener
implementations
Registering TestExecutionListener
implementations with the @TestExecutionListeners
annotation is suitable for special listeners that are used in limited testing scenarios. However, registration can
become difficult if a custom listener needs to be used across the entire test suite. This issue is addressed by
supporting automatic detection of TestExecutionListener
implementations by default through the SpringFactoriesLoader
mechanism.
Specifically, the spring-test
module declares all default TestExecutionListener
implementations in the org.springframework.test.context.TestExecutionListener
key in the file META-INF/spring.factories
properties. Third-party frameworks and developers can add their own TestExecutionListener
implementations to the default listener list in the same way via their own META-INF/spring.factories
properties file.
Ordering TestExecutionListener
If the TestContext framework discovers default TestExecutionListener
implementations through the above
SpringFactoriesLoader
mechanism, the created listener instances are sorted using the AnnotationAwareOrderComparator
of their Spring, which respects the interface Ordered
from Spring and the @Order
annotation for ordering. AbstractTestExecutionListener
and all default
TestExecutionListener
implementations provided by Spring implement Ordered
with
appropriate values. Therefore, third-party frameworks and developers should ensure that their default TestExecutionListener
implementations register in the correct order by implementing Ordered
or declaring the
@Order
annotation. See the javadoc on the getOrder()
methods of the default TestExecutionListener
implementations for more details on what values are assigned to each main listener.
Combining TestExecutionListener
implementations
If a custom listener TestExecutionListener
is registered via the @TestExecutionListeners
annotation, listeners are not registered by default. In most common testing scenarios, this effectively forces the
developer to manually declare all default listeners in addition to any custom listeners. The following listing
demonstrates this configuration style:
@ContextConfiguration
@TestExecutionListeners({
MyCustomTestExecutionListener.class,
ServletTestExecutionListener.class,
DirtiesContextBeforeModesTestExecutionListener.class,
DependencyInjectionTestExecutionListener.class,
DirtiesContextTestExecutionListener.class,
TransactionalTestExecutionListener.class,
SqlScriptsTestExecutionListener.class
})
class MyTest {
// class body...
}
@ContextConfiguration
@TestExecutionListeners(
MyCustomTestExecutionListener::class,
ServletTestExecutionListener::class,
DirtiesContextBeforeModesTestExecutionListener::class,
DependencyInjectionTestExecutionListener::class,
DirtiesContextTestExecutionListener::class,
TransactionalTestExecutionListener::class,
SqlScriptsTestExecutionListener::class
)
class MyTest {
// class body...
}
The difficulty with this approach is that it requires the developer to know exactly which listeners are registered by
default. Moreover, the set of default listeners may change from version to version - for example, the SqlScriptsTestExecutionListener
listener was introduced in Spring Framework 4.1, and the DirtiesContextBeforeModesTestExecutionListener
listener was introduced in Spring Framework 4.2. Moreover, third-party frameworks such as Spring Boot and Spring
Security register their own default TestExecutionListener
implementations using the aforementioned
auto-detection mechanism.
To avoid having to know and re-declare all default listeners, you can set the mergeMode
attribute of the
@TestExecutionListeners
annotation to MergeMode.MERGE_WITH_DEFAULTS
. MERGE_WITH_DEFAULTS
specifies that locally declared listeners should be merged with the default listeners. The merge algorithm ensures
that duplicates are removed from the list and the resulting set of merged listeners is sorted according to the
semantics of AnnotationAwareOrderComparator
, as described in the "Ordering
TestExecutionListener"
implementations section. If a listener implements Ordered
or is
marked with the @Order
annotation, it can influence the position in which it is combined with default
listeners. Otherwise, locally declared listeners are added to the default listener list when merged.
For example, if the MyCustomTestExecutionListener
class in the previous example configured its order
value (for example, 500
) to be less than the order value ServletTestExecutionListener
(which is 1000
), then MyCustomTestExecutionListener
can be automatically combined with a
list of default values before ServletTestExecutionListener
, and the previous the example can be
replaced by the following:
@ContextConfiguration
@TestExecutionListeners(
listeners = MyCustomTestExecutionListener.class,
mergeMode = MERGE_WITH_DEFAULTS
)
class MyTest {
// class body...
}
@ContextConfiguration
@TestExecutionListeners(
listeners = [MyCustomTestExecutionListener::class],
mergeMode = MERGE_WITH_DEFAULTS
)
class MyTest {
// class body...
}