diff --git a/framework-docs/modules/ROOT/pages/testing/annotations/integration-spring/annotation-mockitobean.adoc b/framework-docs/modules/ROOT/pages/testing/annotations/integration-spring/annotation-mockitobean.adoc index 818b8cc2309..6b6de7655db 100644 --- a/framework-docs/modules/ROOT/pages/testing/annotations/integration-spring/annotation-mockitobean.adoc +++ b/framework-docs/modules/ROOT/pages/testing/annotations/integration-spring/annotation-mockitobean.adoc @@ -77,7 +77,7 @@ Java:: [source,java,indent=0,subs="verbatim,quotes"] ---- class OverrideBeanTests { - @MockitoBean(name = "service") // <1> + @MockitoBean("service") // <1> private CustomService customService; // test case body... @@ -121,7 +121,7 @@ Java:: [source,java,indent=0,subs="verbatim,quotes"] ---- class OverrideBeanTests { - @MockitoSpyBean(name = "service") // <1> + @MockitoSpyBean("service") // <1> private CustomService customService; // test case body... diff --git a/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockitoBean.java b/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockitoBean.java index aad8207fc3f..aa221ac4ac1 100644 --- a/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockitoBean.java +++ b/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockitoBean.java @@ -25,6 +25,7 @@ import org.mockito.Answers; import org.mockito.MockSettings; +import org.springframework.core.annotation.AliasFor; import org.springframework.test.context.bean.override.BeanOverride; /** @@ -33,12 +34,12 @@ * {@link org.springframework.context.ApplicationContext ApplicationContext} * using a Mockito mock. * - *
By default, the bean to override is inferred from the type of the annotated + *
By default, the bean to mock is inferred from the type of the annotated * field. If multiple candidates exist, a {@code @Qualifier} annotation can be * used to help disambiguate. In the absence of a {@code @Qualifier} annotation, * the name of the annotated field will be used as a fallback qualifier. - * Alternatively, you can explicitly specify a bean name to replace by setting the - * {@link #name() name} attribute. + * Alternatively, you can explicitly specify a bean name to mock by setting the + * {@link #value() value} or {@link #name() name} attribute. * *
A new bean definition will be created if a corresponding bean definition does * not exist. However, if you would like for the test to fail when a corresponding @@ -52,7 +53,7 @@ * the context alongside the existing dependency. * *
NOTE: Only singleton beans can be overridden. - * Any attempt to override a non-singleton bean will result in an exception. + * Any attempt to mock a non-singleton bean will result in an exception. * * @author Simon Baslé * @author Sam Brannen @@ -67,12 +68,22 @@ public @interface MockitoBean { /** - * The name of the bean to register or replace. - *
If left unspecified, the bean to override is selected according to - * the annotated field's type, taking qualifiers into account if necessary. - * See the {@linkplain MockitoBean class-level documentation} for details. - * @return the name of the mocked bean + * Alias for {@link #name()}. + *
Intended to be used when no other attributes are needed — for + * example, {@code @MockitoBean("customBeanName")}. + * @see #name() */ + @AliasFor("name") + String value() default ""; + + /** + * Name of the bean to mock. + *
If left unspecified, the bean to mock is selected according to the + * annotated field's type, taking qualifiers into account if necessary. See + * the {@linkplain MockitoBean class-level documentation} for details. + * @see #value() + */ + @AliasFor("value") String name() default ""; /** diff --git a/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBean.java b/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBean.java index 4d1f434df6b..ac6225f3a21 100644 --- a/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBean.java +++ b/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBean.java @@ -24,28 +24,32 @@ import org.mockito.Mockito; +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 instance. + * the original bean instance. * - *
If no explicit {@link #name()} is specified, a target bean is selected - * according to the class of the annotated field, and there must be exactly one - * such candidate bean. A {@code @Qualifier} annotation can be used to help - * disambiguate. - * If a {@link #name()} is specified, it is required that a target bean of that - * name has been previously registered in the application context. + *
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 + * used to help disambiguate. In the absence of a {@code @Qualifier} annotation, + * the name of the annotated field will be used as a fallback qualifier. + * Alternatively, you can explicitly specify a bean name to spy by setting the + * {@link #value() value} or {@link #name() name} attribute. If a bean name is + * specified, it is required that a target bean with that name has been previously + * registered in the application context. * - *
Dependencies that are known to the application context but are not beans - * (such as those + *
A spy cannot be created for components which are known to the application + * context but are not beans — for example, components * {@link org.springframework.beans.factory.config.ConfigurableListableBeanFactory#registerResolvableDependency(Class, Object) - * registered directly}) will not be found. + * registered directly} as resolvable dependencies. * - *
NOTE: Only singleton beans can be overridden. - * Any attempt to override a non-singleton bean will result in an exception. + *
NOTE: Only singleton beans can be spied. + * Any attempt to create a spy for a non-singleton bean will result in an exception. * * @author Simon Baslé + * @author Sam Brannen * @since 6.2 * @see org.springframework.test.context.bean.override.mockito.MockitoBean @MockitoBean * @see org.springframework.test.context.bean.override.convention.TestBean @TestBean @@ -57,12 +61,22 @@ public @interface MockitoSpyBean { /** - * The name of the bean to spy. - *
If left unspecified, the bean to spy is selected according to - * the annotated field's type, taking qualifiers into account if necessary. - * See the {@linkplain MockitoSpyBean class-level documentation} for details. - * @return the name of the spied bean + * Alias for {@link #name()}. + *
Intended to be used when no other attributes are needed — for + * example, {@code @MockitoSpyBean("customBeanName")}. + * @see #name() */ + @AliasFor("name") + String value() default ""; + + /** + * Name of the bean to spy. + *
If left unspecified, the bean to spy is selected according to the
+ * annotated field's type, taking qualifiers into account if necessary. See
+ * the {@linkplain MockitoSpyBean class-level documentation} for details.
+ * @see #value()
+ */
+ @AliasFor("value")
String name() default "";
/**
diff --git a/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanContextCustomizerEqualityTests.java b/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanContextCustomizerEqualityTests.java
index a801171ca30..5435a45a121 100644
--- a/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanContextCustomizerEqualityTests.java
+++ b/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanContextCustomizerEqualityTests.java
@@ -17,12 +17,12 @@
package org.springframework.test.context.bean.override.mockito;
import org.junit.jupiter.api.Test;
-import org.mockito.Answers;
import org.springframework.test.context.ContextCustomizer;
import org.springframework.test.context.bean.override.BeanOverrideContextCustomizerTestUtils;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Answers.RETURNS_MOCKS;
/**
* Tests that validate the behavior of {@link MockitoBean} and
@@ -85,7 +85,7 @@ private ContextCustomizer createContextCustomizer(Class> testClass) {
static class Case1ByName {
- @MockitoBean(name = "serviceBean")
+ @MockitoBean("serviceBean")
private String exampleService;
}
@@ -99,7 +99,7 @@ static class Case1ByType {
static class Case2ByName {
- @MockitoBean(name = "serviceBean")
+ @MockitoBean("serviceBean")
private String serviceToMock;
}
@@ -120,14 +120,14 @@ static class Case2ByTypeSameFieldName {
static class Case3 {
- @MockitoBean(answers = Answers.RETURNS_MOCKS)
+ @MockitoBean(answers = RETURNS_MOCKS)
private String exampleService;
}
static class Case4ByName {
- @MockitoSpyBean(name = "serviceBean")
+ @MockitoSpyBean("serviceBean")
private String exampleService;
}
@@ -141,7 +141,7 @@ static class Case4ByType {
static class Case5ByName {
- @MockitoSpyBean(name = "serviceBean")
+ @MockitoSpyBean("serviceBean")
private String serviceToMock;
}
diff --git a/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanForByNameLookupIntegrationTests.java b/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanForByNameLookupIntegrationTests.java
index d2d22530962..321866d464b 100644
--- a/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanForByNameLookupIntegrationTests.java
+++ b/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanForByNameLookupIntegrationTests.java
@@ -36,22 +36,22 @@
@SpringJUnitConfig
public class MockitoBeanForByNameLookupIntegrationTests {
- @MockitoBean(name = "field")
+ @MockitoBean("field")
ExampleService field;
- @MockitoBean(name = "nestedField")
+ @MockitoBean("nestedField")
ExampleService nestedField;
- @MockitoBean(name = "field")
+ @MockitoBean("field")
ExampleService renamed1;
- @MockitoBean(name = "nestedField")
+ @MockitoBean("nestedField")
ExampleService renamed2;
- @MockitoBean(name = "nonExistingBean")
+ @MockitoBean("nonExistingBean")
ExampleService nonExisting1;
- @MockitoBean(name = "nestedNonExistingBean")
+ @MockitoBean("nestedNonExistingBean")
ExampleService nonExisting2;
diff --git a/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanOverrideMetadataTests.java b/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanOverrideMetadataTests.java
index 99aad2960db..0a1a222b5bc 100644
--- a/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanOverrideMetadataTests.java
+++ b/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanOverrideMetadataTests.java
@@ -24,6 +24,7 @@
import org.mockito.Answers;
import org.springframework.core.ResolvableType;
+import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.test.context.bean.override.OverrideMetadata;
import org.springframework.util.ReflectionUtils;
@@ -114,7 +115,7 @@ private Field sampleField(String fieldName) {
}
private MockitoBeanOverrideMetadata createMetadata(Field field) {
- MockitoBean annotation = field.getAnnotation(MockitoBean.class);
+ MockitoBean annotation = AnnotatedElementUtils.getMergedAnnotation(field, MockitoBean.class);
return new MockitoBeanOverrideMetadata(field, ResolvableType.forClass(field.getType()), annotation);
}
@@ -128,7 +129,7 @@ static class SampleOneMock {
static class SampleOneMockWithName {
- @MockitoBean(name = "anotherService")
+ @MockitoBean("anotherService")
String service;
}
@@ -144,7 +145,7 @@ static class Sample {
@MockitoBean(name = "beanToMock")
private String service3;
- @MockitoBean(name = "beanToMock")
+ @MockitoBean(value = "beanToMock")
private String service4;
@MockitoBean(extraInterfaces = Externalizable.class)
diff --git a/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanSettingsStrictIntegrationTests.java b/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanSettingsStrictIntegrationTests.java
index a54fbf3756b..2f998b53598 100644
--- a/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanSettingsStrictIntegrationTests.java
+++ b/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanSettingsStrictIntegrationTests.java
@@ -26,7 +26,6 @@
import org.junit.platform.testkit.engine.EngineTestKit;
import org.junit.platform.testkit.engine.Events;
import org.mockito.exceptions.misusing.UnnecessaryStubbingException;
-import org.mockito.quality.Strictness;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.annotation.DirtiesContext;
@@ -42,6 +41,7 @@
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.BDDMockito.when;
import static org.mockito.Mockito.mock;
+import static org.mockito.quality.Strictness.STRICT_STUBS;
/**
* Integration tests ensuring unnecessary stubbing is reported in various
@@ -85,7 +85,7 @@ void unnecessaryStub() {
@SpringJUnitConfig(Config.class)
@DirtiesContext
- @MockitoBeanSettings(Strictness.STRICT_STUBS)
+ @MockitoBeanSettings(STRICT_STUBS)
static class ExplicitStrictness extends BaseCase {
}
diff --git a/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanWithResetIntegrationTests.java b/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanWithResetIntegrationTests.java
index 7867d154e9b..d75e512170e 100644
--- a/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanWithResetIntegrationTests.java
+++ b/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanWithResetIntegrationTests.java
@@ -33,6 +33,7 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.doReturn;
+import static org.springframework.test.context.bean.override.mockito.MockReset.BEFORE;
/**
* Integration tests for {@link MockitoBean} that validate automatic reset
@@ -45,10 +46,10 @@
@TestMethodOrder(OrderAnnotation.class)
public class MockitoBeanWithResetIntegrationTests {
- @MockitoBean(reset = MockReset.BEFORE)
+ @MockitoBean(reset = BEFORE)
ExampleService service;
- @MockitoBean(reset = MockReset.BEFORE)
+ @MockitoBean(reset = BEFORE)
FailingExampleService failingService;
@Order(1)
diff --git a/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBeanForByNameLookupIntegrationTests.java b/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBeanForByNameLookupIntegrationTests.java
index 14f1d1f4c59..1310a18d436 100644
--- a/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBeanForByNameLookupIntegrationTests.java
+++ b/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBeanForByNameLookupIntegrationTests.java
@@ -40,16 +40,16 @@
@SpringJUnitConfig(Config.class)
public class MockitoSpyBeanForByNameLookupIntegrationTests {
- @MockitoSpyBean(name = "field")
+ @MockitoSpyBean("field")
ExampleService field;
- @MockitoSpyBean(name = "nestedField")
+ @MockitoSpyBean("nestedField")
ExampleService nestedField;
- @MockitoSpyBean(name = "field")
+ @MockitoSpyBean("field")
ExampleService renamed1;
- @MockitoSpyBean(name = "nestedField")
+ @MockitoSpyBean("nestedField")
ExampleService renamed2;
diff --git a/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBeanOverrideMetadataTests.java b/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBeanOverrideMetadataTests.java
index 1872aede339..4c91f431022 100644
--- a/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBeanOverrideMetadataTests.java
+++ b/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBeanOverrideMetadataTests.java
@@ -22,6 +22,7 @@
import org.junit.jupiter.api.Test;
import org.springframework.core.ResolvableType;
+import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.test.context.bean.override.OverrideMetadata;
import org.springframework.util.ReflectionUtils;
@@ -105,7 +106,7 @@ private Field sampleField(String fieldName) {
}
private MockitoSpyBeanOverrideMetadata createMetadata(Field field) {
- MockitoSpyBean annotation = field.getAnnotation(MockitoSpyBean.class);
+ MockitoSpyBean annotation = AnnotatedElementUtils.getMergedAnnotation(field, MockitoSpyBean.class);
return new MockitoSpyBeanOverrideMetadata(field, ResolvableType.forClass(field.getType()), annotation);
}
@@ -119,7 +120,7 @@ static class SampleOneSpy {
static class SampleOneSpyWithName {
- @MockitoSpyBean(name = "anotherService")
+ @MockitoSpyBean("anotherService")
String service;
}
@@ -132,10 +133,10 @@ static class Sample {
@MockitoSpyBean
private String service2;
- @MockitoSpyBean(name = "beanToMock")
+ @MockitoSpyBean(name = "beanToSpy")
private String service3;
- @MockitoSpyBean(name = "beanToMock")
+ @MockitoSpyBean(value = "beanToSpy")
private String service4;
@MockitoSpyBean(reset = MockReset.BEFORE)
diff --git a/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBeanTests.java b/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBeanTests.java
index 86cdb8ca474..fce7ab3f73e 100644
--- a/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBeanTests.java
+++ b/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBeanTests.java
@@ -81,7 +81,7 @@ static class ByTypeSingleLookup {
static class ByNameSingleLookup {
- @MockitoSpyBean(name = "beanToSpy")
+ @MockitoSpyBean("beanToSpy")
String example;
}
diff --git a/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBeanWithResetIntegrationTests.java b/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBeanWithResetIntegrationTests.java
index ced11e1b2d8..cecde1de0dc 100644
--- a/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBeanWithResetIntegrationTests.java
+++ b/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBeanWithResetIntegrationTests.java
@@ -22,11 +22,9 @@
import org.junit.jupiter.api.TestMethodOrder;
import org.springframework.beans.factory.FactoryBean;
-import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
-import org.springframework.lang.Nullable;
import org.springframework.test.context.bean.override.example.ExampleService;
import org.springframework.test.context.bean.override.example.FailingExampleService;
import org.springframework.test.context.bean.override.example.RealExampleService;
@@ -35,6 +33,7 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
import static org.mockito.Mockito.doReturn;
+import static org.springframework.test.context.bean.override.mockito.MockReset.BEFORE;
/**
* Integration tests for {@link MockitoSpyBean} that validate automatic reset
@@ -47,12 +46,13 @@
@TestMethodOrder(OrderAnnotation.class)
public class MockitoSpyBeanWithResetIntegrationTests {
- @MockitoSpyBean(reset = MockReset.BEFORE)
+ @MockitoSpyBean(reset = BEFORE)
ExampleService service;
- @MockitoSpyBean(reset = MockReset.BEFORE)
+ @MockitoSpyBean(name = "failingExampleServiceFactory", reset = BEFORE)
FailingExampleService failingService;
+
@Order(1)
@Test
void beanFirstEstablishingStub(ApplicationContext ctx) {
@@ -83,21 +83,23 @@ void factoryBeanFirstEstablishingStub(ApplicationContext ctx) {
@Order(4)
@Test
void factoryBeanSecondEnsuringStubReset(ApplicationContext ctx) {
- assertThat(ctx.getBean("factory")).isNotNull().isSameAs(this.failingService);
+ assertThat(ctx.getBean("failingExampleServiceFactory"))
+ .isNotNull()
+ .isSameAs(this.failingService);
assertThatIllegalStateException().isThrownBy(this.failingService::greeting)
.as("not stubbed")
.withMessage("Failed");
}
+
static class FailingExampleServiceFactory implements FactoryBean