This commit makes TestClassScanner and TestContextAotGenerator public so
that the Spring Boot team can take over implementation of the
TestAotProcessor to integrate it into the AOT and native build plugins.
This commit introduces support for Netty 5's Buffer, in the form of
Netty5DataBuffer. Because of the new API offered by Buffer, several
changes have been made to the DataBuffer API:
- CloseableDataBuffer is a simpler alternative to PooledDataBuffer, and
implemented by Netty5DataBuffer. DataBufferUtils::release can now
handle CloseableDataBuffer as well as PooledDataBuffer.
- PooledDataBuffer::touch has been moved into a separate interface:
TouchableDataBuffer, which is implemented by Netty5DataBuffer.
- The capacity of DataBuffers can no longer be reduced, they can only
grow larger. As a consequence, DataBuffer::capacity(int) has been
deprecated, but ensureWritable (formally ensureCapacity) still exists.
- DataBuffer::slice and retainedSlice have been deprecated in favor of
split, a new method that ensures that memory regions do not overlap.
- DataBuffer::asByteBuffer has been deprecated in favor of toByteBuffer,
a new method that returns a copy, instead of shared data.
- DataBufferFactory::allocateBuffer has been deprecated in favor of
allocateBuffer(int).
Closes gh-28874
This commit introduces TestAotProcessor which replaces
ProcessTestsAheadOfTimeCommand, removes the dependency on picocli, and
aligns with the implementation of the AotProcessor in Spring Boot.
TestAotProcessor is a command-line application (CLI) that scans the
provided classpath roots for Spring integration test classes and then
generates AOT artifacts for those test classes in the provided output
directories.
This CLI is only intended to be used by build tools.
Closes gh-28825
This commit introduces ProcessTestsAheadOfTimeCommand, a command-line
application (CLI) that scans the provided classpath roots for Spring
integration test classes and then generates AOT artifacts for those
test classes in the provided output directories.
This CLI is only intended to be used by build tools.
Closes gh-28825
This commit introduces initial AOT run-time support in the Spring
TestContext Framework.
- DefaultCacheAwareContextLoaderDelegate: when running in AOT mode, now
loads a test's ApplicationContext via the AotContextLoader SPI
instead of via the standard SmartContextLoader and ContextLoader SPIs.
- DependencyInjectionTestExecutionListener: when running in AOT mode,
now injects dependencies into a test instance using a local instance
of AutowiredAnnotationBeanPostProcessor instead of relying on
AutowireCapableBeanFactory support.
Closes gh-28205
TestContextAotGenerator now uses AotTestMappingsCodeGenerator to
generate a AotTestMappings__Generated.java class which is loaded in
AotTestMappings via reflection in order to retrieve access to
ApplicationContextIntializers generated during AOT processing.
Furthermore, the processAheadOfTimeAndGenerateAotTestMappings() method
in TestContextAotGeneratorTests now performs a rather extensive test
including:
- emulating TestClassScanner to find test classes
- processing all test classes and generating ApplicationContextIntializers
- generating mappings for AotTestMappings
- compiling all generated code
- loading AotTestMappings
- using AotTestMappings to instantiate the generated ApplicationContextIntializer
- using the AotContextLoader API to load the AOT-optimized ApplicationContext
- asserting the behavior of the loaded ApplicationContext
See gh-28205
Closes gh-28204
This commit introduces a dedicated AotContextLoader extension of
SmartContextLoader and reverts the recent changes to the existing
contract for SmartContextLoader. This allows existing
SmartContextLoader implementations to continue working unaffected by
AOT support unless they opt into AOT support by explicitly implementing
the new AotContextLoader contract.
In addition, existing SmartContextLoader implementations in the
spring-test module have been modified to implement AotContextLoader
instead of SmartContextLoader. This allows the core framework to
provide built-in AOT support in the TestContext framework, and it also
allows third-party extensions to built-in SmartContextLoaders to
participate in AOT processing and run-time support transparently (or at
least as transparent as possible).
Closes gh-28906
This commit introduces TestContextAotGenerator for processing Spring
integration test classes and generating AOT artifacts. Specifically,
this class performs the following.
- bootstraps the TCF for a given test class
- builds the MergedContextConfiguration for each test class and tracks
all test classes that share the same MergedContextConfiguration
- loads each test ApplicationContext without refreshing it
- passes the test ApplicationContext to ApplicationContextAotGenerator
to generate the AOT optimized ApplicationContextInitializer
- The GenerationContext passed to ApplicationContextAotGenerator uses
a feature name of the form "TestContext###_", where "###" is a
3-digit sequence ID left padded with zeros.
This commit also includes tests using the TestCompiler to verify that
each generated ApplicationContextInitializer can be used to populate a
GenericApplicationContext as expected.
See gh-28204
Prior to this commit it was possible to configure the
DefaultListableBeanFactory used by the GenericWebApplicationContext
created by AbstractWebGenericContextLoader, but it was not possible to
completely replace the bean factory.
This commit introduces a new createContext() factory method in
AbstractWebGenericContextLoader which indirectly allows subclasses to
supply a custom DefaultListableBeanFactory implementation to the
GenericWebApplicationContext.
See gh-25600
Closes gh-28983
Commit d1b65f6d3e introduced a regression for the handling of
NoClassDefFoundError when skipping a TestExecutionListener that cannot
be loaded. Specifically, the DEBUG log message changed and included the
stack trace; whereas, it previously did not include the stack trace.
This commit consistently handles NoClassDefFoundError for a skipped
TestExecutionListener, whether a default listener or a listener
registered via @TestExecutionListeners and aligns with the previous
behavior by omitting the stack trace for a NoClassDefFoundError.
Closes gh-28962
This commit revises 903e9f2a02 based on feedback from the Spring Boot
team.
- The original loadContext(MergedContextConfiguration) method is no
longer deprecated.
- loadContext(MergedContextConfiguration, boolean) has been replaced by
loadContextForAotProcessing(MergedContextConfiguration) which is
implemented as a `default` method that throws an
UnsupportedOperationException.
- Affected code has been refactored to adjust to these changes.
See gh-28906
Prior to this commit, the contract of the loadContext() method in the
SmartContextLoader SPI required that the ApplicationContext be returned
in a fully refreshed state with a JVM shutdown hook registered for it.
However, in order to support AOT processing within the Spring
TestContext Framework (TCF), we need a way to signal to
SmartContextLoader implementations that they should load the test's
ApplicationContext without refreshing it or registering a JVM shutdown
hook.
To address this issue, this commit:
- Introduces a new loadContext(MergedContextConfiguration, boolean)
method. The boolean `refresh` flag controls whether the returned
ApplicationContext should be refreshed and have a JVM shutdown hook
registered for it.
- Deprecates the existing loadContext(MergedContextConfiguration)
method in favor of loadContext(MergedContextConfiguration, boolean).
- Removes all use of the deprecated method within the spring-test
module, excluding the exception mentioned below.
Note that loadContext(MergedContextConfiguration, boolean) is
implemented as an interface `default` method which delegates to the
deprecated loadContext(MergedContextConfiguration) method for backward
compatibility. When migrating a SmartContextLoader to Spring Framework
6.0, implementations that directly implement the SmartContextLoader SPI
(instead of extending AbstractGenericContextLoader or
AbstractGenericWebContextLoader) will need to override the new
loadContext(MergedContextConfiguration, boolean) method in order to
honor the `refresh` flag for AOT processing support. See the
implementation in AbstractGenericContextLoader for an example of how
this can be achieved.
Closes gh-28906
For Spring Framework 6.0 we have decided to deprecate the obsolete
methods in the ContextLoader API in the Spring TestContext Framework in
favor of the methods in the SmartContextLoader API which has been
available since Spring Framework 3.1.
Closes gh-28905
This commit polishes DefaultGenerationContext to make the method
that flushes generated classes more explicit. It now throws an
IOException and TestGenerationContext has been updated to handle
that to ease its use in code that can't throw such an exception.
As this use case is likely to happen outside the Spring Framework,
this commit adds such a convenience to spring-test as well.
Closes gh-28877
- remove not-empty precondition check for packageNames so that the core
scan() method can actually be used.
- document constructor
- document use case for packageNames
- add test that scan's all test classes in the spring-test project
- reduce logging due to the previous action item
See gh-28824
The search algorithm for @ExtendWith should not be tied to Spring's
@NestedTestConfiguration semantics. Rather, general JUnit annotation
search semantics should be used to find @ExtendWith.
See gh-28824
Commit d1b65f6d3e introduced a regression regarding the handling of
missing dependencies for optional (typically default)
TestExecutionListeners.
Prior to d1b65f6d3e a TestExecutionListener was instantiated using
java.lang.Class.newInstance() which never throws an
InvocationTargetException. With the switch to the new
SpringFactoriesLoader APIs, a TestExecutionListener is now instantiated
using java.lang.reflect.Constructor.newInstance(Object...) which can
throw an InvocationTargetException.
This commit addresses the regression by unwrapping the target exception
in an InvocationTargetException.
See gh-28666
Closes gh-28828
This commit introduces the TestClassScanner which scans provided
classpath roots for Spring integration test classes using the JUnit
Platform Launcher API which allows all registered TestEngines to
discover tests according to their own rules.
The scanner currently detects the following categories of Spring
integration test classes.
- JUnit Jupiter: classes that register the SpringExtension via
@ExtendWith.
- JUnit 4: classes that register the SpringJUnit4ClassRunner or
SpringRunner via @RunWith.
- Generic: classes that are annotated with @ContextConfiguration or
@BootstrapWith.
The scanner has been tested with the following TestEngine
implementations for the JUnit Platform.
- JUnit Jupiter
- JUnit Vintage
- JUnit Platform Suite Engine
- TestNG Engine for the JUnit Platform
Closes gh-28824