Referring to issue #26141, #26142 and most specifically #26143, these are all stemming from attempts by me to create a type of @EnableAcmeLibraryTest
annotation (with optional parameters) that you could slap on a test, and then have both the Spring context and the test instance processed to have the necessary test infrastructure given straight into your hands.
From #26143, @sbrannen pointed me in the direction of ContextCustomizerFactory
with its ContextCustomizer
. This actually seems to fully cover the needs of the first requirement, i.e. tailoring the Spring context before it is refreshed (the other need, tailoring the test instance, would have been covered by TestExecutionListeners
, had it not been for #26141). However, the mechanism is a SPI-style tool, whereby you need to register such factories in a META-INF/spring.factories file on the classpath.
IMO, this is too opaque and "too magic" for my liking. With this I mean that you cannot anymore trust that the code in front of you actually fully represent what will happen - there are also code being "wedged in" from unrelated, seemingly "magic" places.
This SPI-style also makes it harder to use this functionality as a project-specific tool, i.e. "just for these 87 tests in this specific project", due to this being a different and unfamiliar style of coding outside of "pure Java + Spring", introducing opaque aspect-style cross-cutting concerns where some elements are introduced without explicit reference, from a rather different part of the project file tree.
By letting a ContextCustomizer
be introduced declaratively by an annotation (possibly specifying the ContextCustomizerFactory
to instantiate?), you would immediately fix this: As a user of the AcmeLibrary, to get the functionality you desire, you will have to explicitly annotate the test class with a AcmeLibrary-specific annotation making the use obvious, and by only following the code, you could fully understand what happens. Also, for project-specific usages, it would just be clean Java+Spring, no SPI-style META-INF cruft to handle.
It would obviously be a massive positive if it was possible to employ this functionality as a meta-annotation in such a way that the resulting @EnableAcmeLibraryTest
could take annotation parameters which could be employed by the ContextCustomizer[Factory]
to programmatically tailor how the Spring context should be customized. (It should also be implemented in such a way that nothing prevents the @EnableAcmeLibraryTest
to also employ a @TestExecutionListener
to also tailor the test class instance.)
Comment From: sbrannen
We will investigate introducing support for declarative ContextCustomer
registration in the Spring TestContext Framework, potentially for inclusion before 6.0 GA.
Introducing such support would provide a test class aware alternative to ApplicationContextInitializer
.
One option would be to introduce a new @ContextCustomizers
(or @ContextCustomizerFactories
) type-level annotation analogous to @TestExecutionListeners
.
Comment From: stolsvik
Thanks for positive feedback. Please take into account all the three issues I refer to in the OP, which point to a problem when using the annotations @ActiveProfiles
, @ContextConfigration
, and specifically @TestExectionListeners
in "merged" (inherited) modus. The latter would be needed inside the original idea of @EnableAcmeLibraryTest
- but using such annotation would then prevent, by the deficiency these annotations have, the use of them individually on the testclass itself (or would ruin the @EnableAcmeLibraryTest
by not kicking in - I do not remember which one is picked up first)
Comment From: sbrannen
Current work on this feature can be viewed in the following feature branch.
https://github.com/sbrannen/spring-framework/commits/issues/gh-26148-ContextCustomizer-declarative-registration
Comment From: sbrannen
The solution in the aforementioned feature branch is effectively feature complete; however, it is based on the semantics of our @TestExecutionListeners
support which does not allow @ContextCustomizerFactories
to be discovered on multiple, local composed annotations. In other words, just like with @TestExecutionListeners
, only the closest @ContextCustomizerFactories
annotation is taken into account.
I would like to investigate honoring all local @ContextCustomizerFactories
annotations and merging the lists of factories to register. In light of that, I am postponing the continuation of this work to 6.1 M4.
Comment From: sbrannen
Support for @ContextCustomizerFactories
is now available on main
for inclusion in the forthcoming Spring Framework 6.1 M5 release.
Please give it a try and let us know what you think!
- See also #31204