Browse Source

Merge branch '6.2.x'

pull/33928/head
Sam Brannen 1 year ago
parent
commit
ba4105d4f0
  1. 7
      framework-docs/modules/ROOT/pages/testing/annotations/integration-spring/annotation-mockitobean.adoc
  2. 4
      framework-docs/modules/ROOT/pages/testing/annotations/integration-spring/annotation-testbean.adoc
  3. 10
      framework-docs/modules/ROOT/pages/testing/testcontext-framework/bean-overriding.adoc
  4. 2
      spring-test/src/main/java/org/springframework/test/context/bean/override/BeanOverride.java
  5. 3
      spring-test/src/main/java/org/springframework/test/context/bean/override/BeanOverrideHandler.java
  6. 4
      spring-test/src/main/java/org/springframework/test/context/bean/override/convention/TestBean.java
  7. 4
      spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockitoBean.java
  8. 6
      spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBean.java
  9. 14
      spring-test/src/test/java/org/springframework/test/context/bean/override/BeanOverrideHandlerTests.java

7
framework-docs/modules/ROOT/pages/testing/annotations/integration-spring/annotation-mockitobean.adoc

@ -1,9 +1,10 @@ @@ -1,9 +1,10 @@
[[spring-testing-annotation-beanoverriding-mockitobean]]
= `@MockitoBean` and `@MockitoSpyBean`
`@MockitoBean` and `@MockitoSpyBean` are used on fields in test classes to override beans
in the test's `ApplicationContext` with a Mockito _mock_ or _spy_, respectively. In the
latter case, an early instance of the original bean is captured and wrapped by the spy.
`@MockitoBean` and `@MockitoSpyBean` are used on non-static fields in test classes to
override beans in the test's `ApplicationContext` with a Mockito _mock_ or _spy_,
respectively. In the latter case, an early instance of the original bean is captured and
wrapped by the spy.
By default, the annotated field's type is used to search for candidate beans to override.
If multiple candidates match, `@Qualifier` can be provided to narrow the candidate to

4
framework-docs/modules/ROOT/pages/testing/annotations/integration-spring/annotation-testbean.adoc

@ -1,8 +1,8 @@ @@ -1,8 +1,8 @@
[[spring-testing-annotation-beanoverriding-testbean]]
= `@TestBean`
`@TestBean` is used on a field in a test class to override a specific bean in the test's
`ApplicationContext` with an instance provided by a factory method.
`@TestBean` is used on a non-static field in a test class to override a specific bean in
the test's `ApplicationContext` with an instance provided by a factory method.
The associated factory method name is derived from the annotated field's name, or the
bean name if specified. The factory method must be `static`, accept no arguments, and

10
framework-docs/modules/ROOT/pages/testing/testcontext-framework/bean-overriding.adoc

@ -2,7 +2,8 @@ @@ -2,7 +2,8 @@
= Bean Overriding in Tests
Bean overriding in tests refers to the ability to override specific beans in the
`ApplicationContext` for a test class, by annotating one or more fields in the test class.
`ApplicationContext` for a test class, by annotating one or more non-static fields in the
test class.
NOTE: This feature is intended as a less risky alternative to the practice of registering
a bean via `@Bean` with the `DefaultListableBeanFactory`
@ -41,9 +42,10 @@ The `spring-test` module registers implementations of the latter two @@ -41,9 +42,10 @@ The `spring-test` module registers implementations of the latter two
{spring-framework-code}/spring-test/src/main/resources/META-INF/spring.factories[`META-INF/spring.factories`
properties file].
The bean overriding infrastructure searches in test classes for any field meta-annotated
with `@BeanOverride` and instantiates the corresponding `BeanOverrideProcessor` which is
responsible for creating an appropriate `BeanOverrideHandler`.
The bean overriding infrastructure searches in test classes for any non-static field that
is meta-annotated with `@BeanOverride` and instantiates the corresponding
`BeanOverrideProcessor` which is responsible for creating an appropriate
`BeanOverrideHandler`.
The internal `BeanOverrideBeanFactoryPostProcessor` then uses bean override handlers to
alter the test's `ApplicationContext` by creating, replacing, or wrapping beans as

2
spring-test/src/main/java/org/springframework/test/context/bean/override/BeanOverride.java

@ -30,7 +30,7 @@ import org.springframework.aot.hint.annotation.Reflective; @@ -30,7 +30,7 @@ import org.springframework.aot.hint.annotation.Reflective;
* <p>Specifying this annotation registers the configured {@link BeanOverrideProcessor}
* which must be capable of handling the composed annotation and its attributes.
*
* <p>Since the composed annotation should only be applied to fields, it is
* <p>Since the composed annotation should only be applied to non-static fields, it is
* expected that it is meta-annotated with {@link Target @Target(ElementType.FIELD)}.
*
* <p>For concrete examples, see

3
spring-test/src/main/java/org/springframework/test/context/bean/override/BeanOverrideHandler.java

@ -18,6 +18,7 @@ package org.springframework.test.context.bean.override; @@ -18,6 +18,7 @@ package org.springframework.test.context.bean.override;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
@ -105,6 +106,8 @@ public abstract class BeanOverrideHandler { @@ -105,6 +106,8 @@ public abstract class BeanOverrideHandler {
private static void processField(Field field, Class<?> testClass, List<BeanOverrideHandler> handlers) {
AtomicBoolean overrideAnnotationFound = new AtomicBoolean();
MergedAnnotations.from(field, DIRECT).stream(BeanOverride.class).forEach(mergedAnnotation -> {
Assert.state(!Modifier.isStatic(field.getModifiers()),
() -> "@BeanOverride field must not be static: " + field);
MergedAnnotation<?> metaSource = mergedAnnotation.getMetaSource();
Assert.state(metaSource != null, "@BeanOverride annotation must be meta-present");

4
spring-test/src/main/java/org/springframework/test/context/bean/override/convention/TestBean.java

@ -27,8 +27,8 @@ import org.springframework.core.annotation.AliasFor; @@ -27,8 +27,8 @@ import org.springframework.core.annotation.AliasFor;
import org.springframework.test.context.bean.override.BeanOverride;
/**
* {@code @TestBean} is an annotation that can be applied to a field in a test
* class to override a bean in the test's
* {@code @TestBean} is an annotation that can be applied to a non-static field
* in a test class to override a bean in the test's
* {@link org.springframework.context.ApplicationContext ApplicationContext}
* using a static factory method.
*

4
spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockitoBean.java

@ -29,8 +29,8 @@ import org.springframework.core.annotation.AliasFor; @@ -29,8 +29,8 @@ import org.springframework.core.annotation.AliasFor;
import org.springframework.test.context.bean.override.BeanOverride;
/**
* {@code @MockitoBean} is an annotation that can be applied to a field in a test
* class to override a bean in the test's
* {@code @MockitoBean} is an annotation that can be applied to a non-static field
* in a test class to override a bean in the test's
* {@link org.springframework.context.ApplicationContext ApplicationContext}
* using a Mockito mock.
*

6
spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBean.java

@ -26,8 +26,10 @@ import org.springframework.core.annotation.AliasFor; @@ -26,8 +26,10 @@ import org.springframework.core.annotation.AliasFor;
import org.springframework.test.context.bean.override.BeanOverride;
/**
* Mark a field to trigger a bean override using a Mockito spy, which will wrap
* the original bean instance.
* {@code @MockitoSpyBean} is an annotation that can be applied to a non-static
* field in a test class to override a bean in the test's
* {@link org.springframework.context.ApplicationContext ApplicationContext}
* with a Mockito spy that wraps the original bean instance.
*
* <p>By default, the bean to spy is inferred from the type of the annotated
* field. If multiple candidates exist, a {@code @Qualifier} annotation can be

14
spring-test/src/test/java/org/springframework/test/context/bean/override/BeanOverrideHandlerTests.java

@ -86,6 +86,14 @@ class BeanOverrideHandlerTests { @@ -86,6 +86,14 @@ class BeanOverrideHandlerTests {
.withMessageContaining(faultyField.toString());
}
@Test // gh-33922
void forTestClassWithStaticBeanOverrideField() {
Field staticField = field(StaticBeanOverrideField.class, "message");
assertThatIllegalStateException()
.isThrownBy(() -> BeanOverrideHandler.forTestClass(StaticBeanOverrideField.class))
.withMessage("@BeanOverride field must not be static: " + staticField);
}
@Test
void getBeanNameIsNullByDefault() {
BeanOverrideHandler handler = createBeanOverrideHandler(field(ConfigA.class, "noQualifier"));
@ -246,6 +254,12 @@ class BeanOverrideHandlerTests { @@ -246,6 +254,12 @@ class BeanOverrideHandlerTests {
}
}
static class StaticBeanOverrideField {
@DummyBean
static String message;
}
static class ConfigA {
ExampleService noQualifier;

Loading…
Cancel
Save