diff --git a/spring-test/src/main/java/org/springframework/test/context/bean/override/BeanOverrideHandler.java b/spring-test/src/main/java/org/springframework/test/context/bean/override/BeanOverrideHandler.java index fdfc718385a..877a10bbabe 100644 --- a/spring-test/src/main/java/org/springframework/test/context/bean/override/BeanOverrideHandler.java +++ b/spring-test/src/main/java/org/springframework/test/context/bean/override/BeanOverrideHandler.java @@ -243,6 +243,8 @@ public abstract class BeanOverrideHandler { !Objects.equals(this.strategy, that.strategy)) { return false; } + + // by-name lookup if (this.beanName != null) { return true; } diff --git a/spring-test/src/main/java/org/springframework/test/context/bean/override/BeanOverrideRegistry.java b/spring-test/src/main/java/org/springframework/test/context/bean/override/BeanOverrideRegistry.java index fa465e50915..b89c4e7e531 100644 --- a/spring-test/src/main/java/org/springframework/test/context/bean/override/BeanOverrideRegistry.java +++ b/spring-test/src/main/java/org/springframework/test/context/bean/override/BeanOverrideRegistry.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -109,8 +109,7 @@ class BeanOverrideRegistry { void inject(Object target, BeanOverrideHandler handler) { String beanName = this.handlerToBeanNameMap.get(handler); - Assert.state(StringUtils.hasLength(beanName), - () -> "No bean found for BeanOverrideHandler: " + handler); + Assert.state(StringUtils.hasLength(beanName), () -> "No bean found for BeanOverrideHandler: " + handler); inject(handler.getField(), target, beanName); } diff --git a/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockBeans.java b/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockBeans.java index d57c3fe411a..f0b72f50ff0 100644 --- a/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockBeans.java +++ b/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockBeans.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/spring-test/src/test/java/org/springframework/test/context/bean/override/BeanOverrideBeanFactoryPostProcessorTests.java b/spring-test/src/test/java/org/springframework/test/context/bean/override/BeanOverrideBeanFactoryPostProcessorTests.java index a7e29a35a67..8b3ce3c1a6b 100644 --- a/spring-test/src/test/java/org/springframework/test/context/bean/override/BeanOverrideBeanFactoryPostProcessorTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/bean/override/BeanOverrideBeanFactoryPostProcessorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -395,7 +395,7 @@ class BeanOverrideBeanFactoryPostProcessorTests { private static AnnotationConfigApplicationContext createContext(Class testClass) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); - Set handlers = new LinkedHashSet<>(BeanOverrideHandler.forTestClass(testClass)); + Set handlers = new LinkedHashSet<>(BeanOverrideTestUtils.findHandlers(testClass)); new BeanOverrideContextCustomizer(handlers).customizeContext(context, mock(MergedContextConfiguration.class)); return context; } diff --git a/spring-test/src/test/java/org/springframework/test/context/bean/override/BeanOverrideHandlerTests.java b/spring-test/src/test/java/org/springframework/test/context/bean/override/BeanOverrideHandlerTests.java index 1a64107989f..5229cf5b44d 100644 --- a/spring-test/src/test/java/org/springframework/test/context/bean/override/BeanOverrideHandlerTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/bean/override/BeanOverrideHandlerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -51,14 +51,14 @@ class BeanOverrideHandlerTests { @Test void forTestClassWithSingleField() { - List handlers = BeanOverrideHandler.forTestClass(SingleAnnotation.class); + List handlers = BeanOverrideTestUtils.findHandlers(SingleAnnotation.class); assertThat(handlers).singleElement().satisfies(hasBeanOverrideHandler( field(SingleAnnotation.class, "message"), String.class, null)); } @Test void forTestClassWithMultipleFields() { - List handlers = BeanOverrideHandler.forTestClass(MultipleAnnotations.class); + List handlers = BeanOverrideTestUtils.findHandlers(MultipleAnnotations.class); assertThat(handlers).hasSize(2) .anySatisfy(hasBeanOverrideHandler( field(MultipleAnnotations.class, "message"), String.class, null)) @@ -68,7 +68,7 @@ class BeanOverrideHandlerTests { @Test void forTestClassWithMultipleFieldsWithIdenticalMetadata() { - List handlers = BeanOverrideHandler.forTestClass(MultipleAnnotationsDuplicate.class); + List handlers = BeanOverrideTestUtils.findHandlers(MultipleAnnotationsDuplicate.class); assertThat(handlers).hasSize(2) .anySatisfy(hasBeanOverrideHandler( field(MultipleAnnotationsDuplicate.class, "message1"), String.class, "messageBean")) @@ -81,7 +81,7 @@ class BeanOverrideHandlerTests { void forTestClassWithCompetingBeanOverrideAnnotationsOnSameField() { Field faultyField = field(MultipleAnnotationsOnSameField.class, "message"); assertThatIllegalStateException() - .isThrownBy(() -> BeanOverrideHandler.forTestClass(MultipleAnnotationsOnSameField.class)) + .isThrownBy(() -> BeanOverrideTestUtils.findHandlers(MultipleAnnotationsOnSameField.class)) .withMessageStartingWith("Multiple @BeanOverride annotations found") .withMessageContaining(faultyField.toString()); } @@ -90,7 +90,7 @@ class BeanOverrideHandlerTests { void forTestClassWithStaticBeanOverrideField() { Field staticField = field(StaticBeanOverrideField.class, "message"); assertThatIllegalStateException() - .isThrownBy(() -> BeanOverrideHandler.forTestClass(StaticBeanOverrideField.class)) + .isThrownBy(() -> BeanOverrideTestUtils.findHandlers(StaticBeanOverrideField.class)) .withMessage("@BeanOverride field must not be static: " + staticField); } diff --git a/spring-test/src/test/java/org/springframework/test/context/bean/override/BeanOverrideTestUtils.java b/spring-test/src/test/java/org/springframework/test/context/bean/override/BeanOverrideTestUtils.java new file mode 100644 index 00000000000..8932a072c84 --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/bean/override/BeanOverrideTestUtils.java @@ -0,0 +1,33 @@ +/* + * Copyright 2002-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.test.context.bean.override; + +import java.util.List; + +/** + * Test utilities for Bean Overrides. + * + * @author Sam Brannen + * @since 6.2.2 + */ +public abstract class BeanOverrideTestUtils { + + public static List findHandlers(Class testClass) { + return BeanOverrideHandler.forTestClass(testClass); + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/context/bean/override/convention/TestBeanOverrideHandlerTests.java b/spring-test/src/test/java/org/springframework/test/context/bean/override/convention/TestBeanOverrideHandlerTests.java index c79dda50aa1..f95fe62912a 100644 --- a/spring-test/src/test/java/org/springframework/test/context/bean/override/convention/TestBeanOverrideHandlerTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/bean/override/convention/TestBeanOverrideHandlerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,6 +26,7 @@ import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.core.ResolvableType; import org.springframework.test.context.bean.override.BeanOverrideHandler; import org.springframework.test.context.bean.override.BeanOverrideStrategy; +import org.springframework.test.context.bean.override.BeanOverrideTestUtils; import org.springframework.util.ReflectionUtils; import org.springframework.util.StringUtils; @@ -42,21 +43,21 @@ import static org.assertj.core.api.Assertions.assertThatIllegalStateException; class TestBeanOverrideHandlerTests { @Test - void setsBeanNameToNullIfAnnotationNameIsNull() { - List handlers = BeanOverrideHandler.forTestClass(SampleOneOverride.class); + void beanNameIsSetToNullIfAnnotationNameIsEmpty() { + List handlers = BeanOverrideTestUtils.findHandlers(SampleOneOverride.class); assertThat(handlers).singleElement().extracting(BeanOverrideHandler::getBeanName).isNull(); } @Test - void setsBeanNameToAnnotationName() { - List handlers = BeanOverrideHandler.forTestClass(SampleOneOverrideWithName.class); + void beanNameIsSetToAnnotationName() { + List handlers = BeanOverrideTestUtils.findHandlers(SampleOneOverrideWithName.class); assertThat(handlers).singleElement().extracting(BeanOverrideHandler::getBeanName).isEqualTo("anotherBean"); } @Test void failsWithMissingMethod() { assertThatIllegalStateException() - .isThrownBy(() -> BeanOverrideHandler.forTestClass(SampleMissingMethod.class)) + .isThrownBy(() -> BeanOverrideTestUtils.findHandlers(SampleMissingMethod.class)) .withMessage("No static method found named message() in %s with return type %s", SampleMissingMethod.class.getName(), String.class.getName()); } diff --git a/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanOverrideHandlerTests.java b/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanOverrideHandlerTests.java index 6a44a83f137..72fc58149da 100644 --- a/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanOverrideHandlerTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanOverrideHandlerTests.java @@ -26,6 +26,7 @@ import org.mockito.Answers; import org.springframework.core.ResolvableType; import org.springframework.core.annotation.AnnotatedElementUtils; import org.springframework.test.context.bean.override.BeanOverrideHandler; +import org.springframework.test.context.bean.override.BeanOverrideTestUtils; import org.springframework.util.ReflectionUtils; import static org.assertj.core.api.Assertions.assertThat; @@ -34,87 +35,89 @@ import static org.assertj.core.api.Assertions.assertThat; * Tests for {@link MockitoBeanOverrideHandler}. * * @author Stephane Nicoll + * @author Sam Brannen + * @since 6.2 */ class MockitoBeanOverrideHandlerTests { @Test - void forTestClassSetsNameToNullIfAnnotationNameIsNull() { - List list = BeanOverrideHandler.forTestClass(SampleOneMock.class); + void beanNameIsSetToNullIfAnnotationNameIsEmpty() { + List list = BeanOverrideTestUtils.findHandlers(SampleOneMock.class); assertThat(list).singleElement().satisfies(handler -> assertThat(handler.getBeanName()).isNull()); } @Test - void forTestClassSetsNameToAnnotationName() { - List list = BeanOverrideHandler.forTestClass(SampleOneMockWithName.class); + void beanNameIsSetToAnnotationName() { + List list = BeanOverrideTestUtils.findHandlers(SampleOneMockWithName.class); assertThat(list).singleElement().satisfies(handler -> assertThat(handler.getBeanName()).isEqualTo("anotherService")); } @Test - void isEqualToWithSameInstance() { - MockitoBeanOverrideHandler handler = createBeanOverrideHandler(sampleField("service")); + void isEqualToWithSameInstanceFromField() { + MockitoBeanOverrideHandler handler = createHandler(sampleField("service")); assertThat(handler).isEqualTo(handler); assertThat(handler).hasSameHashCodeAs(handler); } @Test - void isEqualToWithSameMetadata() { - MockitoBeanOverrideHandler handler1 = createBeanOverrideHandler(sampleField("service")); - MockitoBeanOverrideHandler handler2 = createBeanOverrideHandler(sampleField("service")); + void isEqualToWithSameMetadataFromField() { + MockitoBeanOverrideHandler handler1 = createHandler(sampleField("service")); + MockitoBeanOverrideHandler handler2 = createHandler(sampleField("service")); assertThat(handler1).isEqualTo(handler2); assertThat(handler1).hasSameHashCodeAs(handler2); } @Test void isNotEqualEqualToByTypeLookupWithSameMetadataButDifferentField() { - MockitoBeanOverrideHandler handler1 = createBeanOverrideHandler(sampleField("service")); - MockitoBeanOverrideHandler handler2 = createBeanOverrideHandler(sampleField("service2")); + MockitoBeanOverrideHandler handler1 = createHandler(sampleField("service")); + MockitoBeanOverrideHandler handler2 = createHandler(sampleField("service2")); assertThat(handler1).isNotEqualTo(handler2); } @Test void isEqualEqualToByNameLookupWithSameMetadataButDifferentField() { - MockitoBeanOverrideHandler handler1 = createBeanOverrideHandler(sampleField("service3")); - MockitoBeanOverrideHandler handler2 = createBeanOverrideHandler(sampleField("service4")); + MockitoBeanOverrideHandler handler1 = createHandler(sampleField("service3")); + MockitoBeanOverrideHandler handler2 = createHandler(sampleField("service4")); assertThat(handler1).isEqualTo(handler2); assertThat(handler1).hasSameHashCodeAs(handler2); } @Test void isNotEqualToWithSameMetadataButDifferentBeanName() { - MockitoBeanOverrideHandler handler1 = createBeanOverrideHandler(sampleField("service")); - MockitoBeanOverrideHandler handler2 = createBeanOverrideHandler(sampleField("service3")); + MockitoBeanOverrideHandler handler1 = createHandler(sampleField("service")); + MockitoBeanOverrideHandler handler2 = createHandler(sampleField("service3")); assertThat(handler1).isNotEqualTo(handler2); } @Test void isNotEqualToWithSameMetadataButDifferentExtraInterfaces() { - MockitoBeanOverrideHandler handler1 = createBeanOverrideHandler(sampleField("service")); - MockitoBeanOverrideHandler handler2 = createBeanOverrideHandler(sampleField("service5")); + MockitoBeanOverrideHandler handler1 = createHandler(sampleField("service")); + MockitoBeanOverrideHandler handler2 = createHandler(sampleField("service5")); assertThat(handler1).isNotEqualTo(handler2); } @Test void isNotEqualToWithSameMetadataButDifferentAnswers() { - MockitoBeanOverrideHandler handler1 = createBeanOverrideHandler(sampleField("service")); - MockitoBeanOverrideHandler handler2 = createBeanOverrideHandler(sampleField("service6")); + MockitoBeanOverrideHandler handler1 = createHandler(sampleField("service")); + MockitoBeanOverrideHandler handler2 = createHandler(sampleField("service6")); assertThat(handler1).isNotEqualTo(handler2); } @Test void isNotEqualToWithSameMetadataButDifferentSerializableFlag() { - MockitoBeanOverrideHandler handler1 = createBeanOverrideHandler(sampleField("service")); - MockitoBeanOverrideHandler handler2 = createBeanOverrideHandler(sampleField("service7")); + MockitoBeanOverrideHandler handler1 = createHandler(sampleField("service")); + MockitoBeanOverrideHandler handler2 = createHandler(sampleField("service7")); assertThat(handler1).isNotEqualTo(handler2); } - private Field sampleField(String fieldName) { + private static Field sampleField(String fieldName) { Field field = ReflectionUtils.findField(Sample.class, fieldName); assertThat(field).isNotNull(); return field; } - private MockitoBeanOverrideHandler createBeanOverrideHandler(Field field) { + private static MockitoBeanOverrideHandler createHandler(Field field) { MockitoBean annotation = AnnotatedElementUtils.getMergedAnnotation(field, MockitoBean.class); return new MockitoBeanOverrideHandler(field, ResolvableType.forClass(field.getType()), annotation); } @@ -124,14 +127,12 @@ class MockitoBeanOverrideHandlerTests { @MockitoBean String service; - } static class SampleOneMockWithName { @MockitoBean("anotherService") String service; - } static class Sample { @@ -156,7 +157,6 @@ class MockitoBeanOverrideHandlerTests { @MockitoBean(serializable = true) private String service7; - } } diff --git a/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanOverrideProcessorTests.java b/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanOverrideProcessorTests.java index fccb4b25eec..d25475990b4 100644 --- a/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanOverrideProcessorTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanOverrideProcessorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,56 +24,60 @@ import org.junit.jupiter.api.Test; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.lang.Nullable; import org.springframework.test.context.bean.override.BeanOverrideHandler; -import org.springframework.test.context.bean.override.example.ExampleService; +import org.springframework.util.ReflectionUtils; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalStateException; /** - * Tests for {@link MockitoBeanOverrideProcessorTests} + * Tests for {@link MockitoBeanOverrideProcessor}. + * + * @author Simon Baslé + * @author Sam Brannen + * @since 6.2 */ -public class MockitoBeanOverrideProcessorTests { +class MockitoBeanOverrideProcessorTests { private final MockitoBeanOverrideProcessor processor = new MockitoBeanOverrideProcessor(); + + private final Field field = ReflectionUtils.findField(TestCase.class, "number"); + + @Test - void mockAnnotationCreatesMockitoBeanOverrideHandler() throws NoSuchFieldException { + void mockAnnotationCreatesMockitoBeanOverrideHandler() { MockitoBean annotation = AnnotationUtils.synthesizeAnnotation(MockitoBean.class); - Class clazz = MockitoConf.class; - Field field = clazz.getField("a"); - BeanOverrideHandler object = this.processor.createHandler(annotation, clazz, field); + BeanOverrideHandler object = processor.createHandler(annotation, TestCase.class, field); assertThat(object).isExactlyInstanceOf(MockitoBeanOverrideHandler.class); } @Test - void spyAnnotationCreatesMockitoSpyBeanOverrideHandler() throws NoSuchFieldException { + void spyAnnotationCreatesMockitoSpyBeanOverrideHandler() { MockitoSpyBean annotation = AnnotationUtils.synthesizeAnnotation(MockitoSpyBean.class); - Class clazz = MockitoConf.class; - Field field = clazz.getField("a"); - BeanOverrideHandler object = this.processor.createHandler(annotation, clazz, field); + BeanOverrideHandler object = processor.createHandler(annotation, TestCase.class, field); assertThat(object).isExactlyInstanceOf(MockitoSpyBeanOverrideHandler.class); } @Test - void otherAnnotationThrows() throws NoSuchFieldException { - Class clazz = MockitoConf.class; - Field field = clazz.getField("a"); + void otherAnnotationThrows() { Annotation annotation = field.getAnnotation(Nullable.class); assertThatIllegalStateException() - .isThrownBy(() -> this.processor.createHandler(annotation, clazz, field)) + .isThrownBy(() -> processor.createHandler(annotation, TestCase.class, field)) .withMessage("Invalid annotation passed to MockitoBeanOverrideProcessor: expected either " + "@MockitoBean or @MockitoSpyBean on field %s.%s", field.getDeclaringClass().getName(), field.getName()); } - static class MockitoConf { + + static class TestCase { + @Nullable @MockitoBean @MockitoSpyBean - public ExampleService a; + Integer number; } } diff --git a/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBeanOverrideHandlerTests.java b/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBeanOverrideHandlerTests.java index 95e952bd014..733598f3859 100644 --- a/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBeanOverrideHandlerTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBeanOverrideHandlerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2024 the original author or authors. + * Copyright 2002-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,6 +24,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.BeanOverrideHandler; +import org.springframework.test.context.bean.override.BeanOverrideTestUtils; import org.springframework.util.ReflectionUtils; import static org.assertj.core.api.Assertions.assertThat; @@ -36,14 +37,14 @@ import static org.assertj.core.api.Assertions.assertThat; class MockitoSpyBeanOverrideHandlerTests { @Test - void forTestClassSetsNameToNullIfAnnotationNameIsNull() { - List list = BeanOverrideHandler.forTestClass(SampleOneSpy.class); + void beanNameIsSetToNullIfAnnotationNameIsEmpty() { + List list = BeanOverrideTestUtils.findHandlers(SampleOneSpy.class); assertThat(list).singleElement().satisfies(handler -> assertThat(handler.getBeanName()).isNull()); } @Test - void forTestClassSetsNameToAnnotationName() { - List list = BeanOverrideHandler.forTestClass(SampleOneSpyWithName.class); + void beanNameIsSetToAnnotationName() { + List list = BeanOverrideTestUtils.findHandlers(SampleOneSpyWithName.class); assertThat(list).singleElement().satisfies(handler -> assertThat(handler.getBeanName()).isEqualTo("anotherService")); }