Prior to this commit, we found in gh-35953 that using the `WebTestClient`
the following way leaks data buffers:
```
var body = client.get().uri("download")
.exchange()
.expectStatus().isOk()
.returnResult()
.getResponseBodyContent();
```
Here, the test performs expectations on the response status and headers,
but not on the response body. The WiretapConnector already supports this
case by subscribing to the Flux response body in those cases and
accumulating the entire content as a single byte[].
Here, the `DataBuffer` instances are not decoded by any `Decoder` and
are not released. This results in a memory leak.
This commit ensures that the automatic subscription in
`WiretapConnector` also releases the buffers automatically as the DSL
does not allow at that point to go back to performing body expectations.
Fixes gh-36050
Prior to this commit, if an enclosing test class (such as one annotated
with @SpringBootTest or simply @ExtendWith(SpringExtension.class))
was not annotated with @ContextConfiguration (or @Import with
@SpringBootTest), the ApplicationContext loaded for a @Nested test
class would not use any default context configuration for the enclosing
test class.
Effectively, a default XML configuration file or static nested
@Configuration class for the enclosing test class was not discovered
by the AbstractTestContextBootstrapper when attempting to build the
MergedContextConfiguration (application context cache key).
To address that, this commit introduces a new
resolveDefaultContextConfigurationAttributes() method in
ContextLoaderUtils which is responsible for creating instances of
ContextConfigurationAttributes for all superclasses and enclosing
classes. This effectively enables AbstractTestContextBootstrapper to
delegate to the resolved SmartContextLoader to properly detect a
default XML configuration file or static nested @Configuration class
even if such classes are not annotated with @ContextConfiguration.
Closes gh-31456
Prior to this commit, `RestTestClient` tests could only perform
expectations on the response without consuming the body. In this case,
the client could leak HTTP connections with the underlying HTTP library
because the response was not entirely read.
This commit ensures that the response is always fully drained before
performing expectations. The client is configured to buffer the response
content, so further body expectations are always possible.
Fixes gh-35784
This commit picks up where commit a0baeae9cf left off.
Specifically, in order to align with the behavior of
AbstractMockHttpServletRequestBuilder, HtmlUnitRequestBuilder no longer
sets the local port in the MockHttpServletRequest.
See gh-35709
Prior to this commit, HtmlUnitRequestBuilder set the server port in the
MockHttpServletRequest to -1 if the URL did not contain an explicit
port. However, that can lead to errors in consumers of the request that
do not expect an invalid port number.
In addition, HtmlUnitRequestBuilder always set the remote port in the
MockHttpServletRequest to the value of the server port, which does not
make sense, since the remote port of the client has nothing to do with
the port on the server.
To address those issues, this commit revises HtmlUnitRequestBuilder so
that it:
- Does not set the server and local ports if the explicit or derived
default value is -1.
- Consistently sets the server and local ports to the same valid value.
- Does not set the remote port.
Closes gh-35709
Although @PersistenceContext and @PersistenceUnit are still not
supported in tests running in AOT mode, as of Spring Framework 7.0,
developers can inject an EntityManager or EntityManagerFactory into
tests using @Autowired instead of @PersistenceContext and
@PersistenceUnit, respectively.
See commit 096303c477
See gh-33414
Closes gh-31442
The JsonConverterDelegate interface replaces usages of
HttpMessageContentConverter to provides the flexibility to use either
message converters or WebFlux codecs.
HttpMessageContentConverter is deprecated, and replaced with a package
private copy (DefaultJsonConverterDelegate) in the
org.springframework.test.json package that is accessible through
a static method on JsonConverterDelegate.
See gh-35737
Prior to this commit, an attempt to use @MockitoSpyBean to spy on a
scoped proxy configured with
@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS) resulted in an
exception thrown by Mockito when the spy was stubbed. The exception
message stated "Failed to unwrap proxied object" but did not provide
any further insight or context for the user.
The reason is that ScopedProxyFactoryBean is used to create such a
scoped proxy, which uses a SimpleBeanTargetSource, which is not a
static TargetSource. Consequently,
SpringMockResolver.getUltimateTargetObject(Object) is not able to
unwrap the proxy.
In order to improve diagnostics for users, this commit eagerly detects
an attempt to spy on a scoped proxy and throws an exception with a
meaningful message. The following is an example, trimmed stack trace
from the test suite.
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'myScopedProxy': Post-processing of
FactoryBean's singleton object failed
...
Caused by: java.lang.IllegalStateException:
@MockitoSpyBean cannot be applied to bean 'myScopedProxy', because
it is a Spring AOP proxy with a non-static TargetSource. Perhaps you
have attempted to spy on a scoped proxy, which is not supported.
at ...MockitoSpyBeanOverrideHandler.createSpy(MockitoSpyBeanOverrideHandler.java:78)
Closes gh-35722
This commit adds AOT support for discovering @Nested test classes
within a @ClassTemplate test class, which includes
@ParameterizedClass test classes.
Closes gh-35744
Switching from @PersistenceContext to @Autowired for dependency
injection in tests allows such tests to participate in AOT processing.
Note, however, that we still have TestNG-based tests that use
@PersistenceContext — for example, AbstractEjbTxDaoTestNGTests.
See gh-29122
See gh-31442
See gh-33414
The MockMvcClientHttpRequestFactoryTests variant for RestTestClient was
copied from MockMvcClientHttpRequestFactoryTests which actually uses
MockMvcClientHttpRequestFactory. In addition,
MockMvcClientHttpRequestFactoryTests unnecessarily used the
SpringExtension.
This commit therefore renames the class to MockMvcRestTestClientTests
and removes the use of the SpringExtension.
See gh-29122
This commit upgrades our test suite to use JUnit 6.0.1 and removes the
systemProperty("junit.platform.discovery.issue.severity.critical", "WARNING")
configuration from spring-test.gradle, so that all discovery issues will
fail the build for the spring-test module as well.
In addition, this commit prevents potential AOT test scanning failures
for JUnit 4 tests by setting the
"junit.vintage.discovery.issue.reporting.enabled" configuration
parameter to "false" in TestClassScanner.
See https://github.com/junit-team/junit-framework/issues/5030
Closes gh-35740
As of Spring Framework 6.2.13, we support JUnit Jupiter 5.12's
ExtensionContextScope.TEST_METHOD behavior in the SpringExtension and
the BeanOverrideTestExecutionListener; however, users can only benefit
from that if they explicitly set the following configuration parameter
for their entire test suite, which may have adverse effects on other
third-party JUnit Jupiter extensions.
junit.jupiter.extensions.testinstantiation.extensioncontextscope.default=test_method
For Spring Framework 7.0, in order to support dependency injection into
test class constructors and fields in @Nested test class hierarchies
from the same ApplicationContext that is already used to perform
dependency injection into lifecycle and test methods (@BeforeEach,
@AfterEach, @Test, etc.), we have decided to configure the
SpringExtension to use ExtensionContextScope.TEST_METHOD by default. In
addition, we have decided to provide a mechanism for users to switch
back to the legacy "test-class scoped ExtensionContext" behavior in
case third-party TestExecutionListener implementations are not yet
compatible with test-method scoped ExtensionContext and TestContext
semantics.
This commit achieves the above goals as follows.
- A new @SpringExtensionConfig annotation has been introduced, which
allows developers to configure the effective ExtensionContext scope
used by the SpringExtension.
- The SpringExtension now overrides
getTestInstantiationExtensionContextScope() to return
ExtensionContextScope.TEST_METHOD.
- The postProcessTestInstance() and resolveParameter() methods in the
SpringExtension now find the properly scoped ExtensionContext for the
supplied test class, based on whether the @Nested test class
hierarchy is annotated with
@SpringExtensionConfig(useTestClassScopedExtensionContext = true).
See gh-35680
See gh-35716
Closes gh-35697
Since we now officially support the TEST_METHOD ExtensionContextScope
(see gh-35676 and gh-35680), this commit introduces tests which
demonstrate that the issue raised in gh-34576 is no longer an "issue" if
the user indirectly configures the SpringExtension to use the TEST_METHOD
scope via the "junit.jupiter.extensions.testinstantiation.extensioncontextscope.default"
configuration parameter.
Historically, @Autowired fields in an enclosing class of a @Nested
test class have been injected from the ApplicationContext for the
enclosing class. If the enclosing test class and @Nested test class
share the same ApplicationContext configuration, things work as
developers expect. However, if the enclosing class and @Nested test
class have different ApplicationContexts, that can lead to
difficult-to-debug scenarios. For example, a bean injected into the
enclosing test class will not participate in a test-managed transaction
in the @Nested test class (see gh-34576).
JUnit Jupiter 5.12 introduced a new ExtensionContextScope feature which
allows the SpringExtension to behave the same for @Autowired fields as
it already does for @Autowired arguments in lifecycle and test
methods. Specifically, if a developer sets the ExtensionContextScope to
TEST_METHOD — for example, by configuring the following configuration
parameter as a JVM system property or in a `junit-platform.properties`
file — the SpringExtension already supports dependency injection from
the current, @Nested ApplicationContext in @Autowired fields in an
enclosing class of the @Nested test class.
junit.jupiter.extensions.testinstantiation.extensioncontextscope.default=test_method
However, there are two scenarios that fail as of Spring Framework
6.2.12.
1. @TestConstructor configuration in @Nested class hierarchies.
2. Field injection for bean overrides (such as @MockitoBean) in
@Nested class hierarchies.
Commit 82c34f7b51 fixed the SpringExtension to support scenario #2
above.
To fix scenario #1, this commit revises
BeanOverrideTestExecutionListener's injectField() implementation to
look up the fields to inject for the "current test instance" instead of
for the "current test class".
This commit also introduces tests for both scenarios.
See gh-34576
See gh-35676
Closes gh-35680
This commit introduces a new isAutowirableConstructor(Executable, PropertyProvider)
overload in TestConstructorUtils and deprecates all other existing variants
for removal in 7.1.
Closes gh-35676
Prior to this commit, the BeanOverrideBeanFactoryPostProcessor rejected
any attempt to override a non-singleton bean; however, due to interest
from the community, we have decided to provide support for overriding
non-singleton beans via the Bean Override mechanism — for example, when
using @MockitoBean, @MockitoSpyBean, and @TestBean.
With this commit, we now support Bean Overrides for non-singletons: for
standard JVM runtimes as well as AOT processing and AOT runtimes. This
commit also documents that non-singletons will effectively be converted
to singletons when overridden and logs a warning similar to the
following.
WARN: BeanOverrideBeanFactoryPostProcessor - Converting 'prototype' scoped bean definition 'myBean' to a singleton.
See gh-33602
See gh-32933
See gh-33800
Closes gh-35574
At some point, TestNG started implementing listener methods as interface
default methods, so we no longer need to override those methods with
empty implementations.
Prior to this commit, AbstractTestNGSpringContextTests was not
thread-safe with regard to tracked exceptions.
To address that, AbstractTestNGSpringContextTests now tracks the test
exception via a ThreadLocal.
Closes gh-35528