From 3a7185206edc912166e3a3672192f9a711f4e4c3 Mon Sep 17 00:00:00 2001 From: Bernardo Bulgarelli Date: Tue, 4 Jul 2023 22:28:02 -0300 Subject: [PATCH 1/2] Check for Class and ResolvableType object type attributes See gh-36224 --- .../mock/mockito/MockitoPostProcessor.java | 13 +++++++++- .../mockito/MockitoPostProcessorTests.java | 26 +++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/mock/mockito/MockitoPostProcessor.java b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/mock/mockito/MockitoPostProcessor.java index f5d0e0ee3e9..254c18b475f 100644 --- a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/mock/mockito/MockitoPostProcessor.java +++ b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/mock/mockito/MockitoPostProcessor.java @@ -254,7 +254,18 @@ public class MockitoPostProcessor implements InstantiationAwareBeanPostProcessor for (String beanName : beanFactory.getBeanNamesForType(FactoryBean.class, true, false)) { beanName = BeanFactoryUtils.transformedBeanName(beanName); BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName); - if (typeName.equals(beanDefinition.getAttribute(FactoryBean.OBJECT_TYPE_ATTRIBUTE))) { + Object attribute = beanDefinition.getAttribute(FactoryBean.OBJECT_TYPE_ATTRIBUTE); + if(attribute instanceof Class) { + Class attributeClass = (Class) attribute; + if (typeName.equals(attributeClass.getName())) { + beans.add(beanName); + } + } else if (attribute instanceof ResolvableType) { + ResolvableType resolvableType = (ResolvableType) attribute; + if (typeName.equals(resolvableType.resolve(Object.class).getName())) { + beans.add(beanName); + } + } else if (typeName.equals(attribute)){ beans.add(beanName); } } diff --git a/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/MockitoPostProcessorTests.java b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/MockitoPostProcessorTests.java index 4e6a0660636..b5b44d693cd 100644 --- a/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/MockitoPostProcessorTests.java +++ b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/MockitoPostProcessorTests.java @@ -36,6 +36,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.core.Ordered; +import org.springframework.core.ResolvableType; import org.springframework.test.util.ReflectionTestUtils; import org.springframework.util.Assert; @@ -84,6 +85,31 @@ class MockitoPostProcessorTests { assertThat(Mockito.mockingDetails(context.getBean("beanToBeMocked")).isMock()).isTrue(); } + @Test + void canMockBeanProducedByFactoryBeanWithClassAttribute() { + AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); + MockitoPostProcessor.register(context); + RootBeanDefinition factoryBeanDefinition = new RootBeanDefinition(TestFactoryBean.class); + factoryBeanDefinition.setAttribute(FactoryBean.OBJECT_TYPE_ATTRIBUTE, SomeInterface.class); + context.registerBeanDefinition("beanToBeMocked", factoryBeanDefinition); + context.register(MockedFactoryBean.class); + context.refresh(); + assertThat(Mockito.mockingDetails(context.getBean("beanToBeMocked")).isMock()).isTrue(); + } + + @Test + void canMockBeanProducedByFactoryBeanWithResolvableTypeAttribute() { + AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); + MockitoPostProcessor.register(context); + RootBeanDefinition factoryBeanDefinition = new RootBeanDefinition(TestFactoryBean.class); + ResolvableType objectType = ResolvableType.forClass(SomeInterface.class); + factoryBeanDefinition.setAttribute(FactoryBean.OBJECT_TYPE_ATTRIBUTE, objectType); + context.registerBeanDefinition("beanToBeMocked", factoryBeanDefinition); + context.register(MockedFactoryBean.class); + context.refresh(); + assertThat(Mockito.mockingDetails(context.getBean("beanToBeMocked")).isMock()).isTrue(); + } + @Test void canMockPrimaryBean() { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); From f4c996b4324bb127ef26a63a9306d0bf133519c3 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 5 Jul 2023 09:04:58 +0100 Subject: [PATCH 2/2] Polish "Check for Class and ResolvableType object type attributes" See gh-36224 --- .../mock/mockito/MockitoPostProcessor.java | 21 +++++++------------ .../mockito/MockitoPostProcessorTests.java | 6 +++--- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/mock/mockito/MockitoPostProcessor.java b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/mock/mockito/MockitoPostProcessor.java index 254c18b475f..ec66aa12ffa 100644 --- a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/mock/mockito/MockitoPostProcessor.java +++ b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/mock/mockito/MockitoPostProcessor.java @@ -248,29 +248,22 @@ public class MockitoPostProcessor implements InstantiationAwareBeanPostProcessor return candidates; } - private Set getExistingBeans(ConfigurableListableBeanFactory beanFactory, ResolvableType type) { - Set beans = new LinkedHashSet<>(Arrays.asList(beanFactory.getBeanNamesForType(type, true, false))); - String typeName = type.resolve(Object.class).getName(); + private Set getExistingBeans(ConfigurableListableBeanFactory beanFactory, ResolvableType resolvableType) { + Set beans = new LinkedHashSet<>( + Arrays.asList(beanFactory.getBeanNamesForType(resolvableType, true, false))); + Class type = resolvableType.resolve(Object.class); + String typeName = type.getName(); for (String beanName : beanFactory.getBeanNamesForType(FactoryBean.class, true, false)) { beanName = BeanFactoryUtils.transformedBeanName(beanName); BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName); Object attribute = beanDefinition.getAttribute(FactoryBean.OBJECT_TYPE_ATTRIBUTE); - if(attribute instanceof Class) { - Class attributeClass = (Class) attribute; - if (typeName.equals(attributeClass.getName())) { - beans.add(beanName); - } - } else if (attribute instanceof ResolvableType) { - ResolvableType resolvableType = (ResolvableType) attribute; - if (typeName.equals(resolvableType.resolve(Object.class).getName())) { - beans.add(beanName); - } - } else if (typeName.equals(attribute)){ + if (resolvableType.equals(attribute) || type.equals(attribute) || typeName.equals(attribute)) { beans.add(beanName); } } beans.removeIf(this::isScopedTarget); return beans; + } private boolean isScopedTarget(String beanName) { diff --git a/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/MockitoPostProcessorTests.java b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/MockitoPostProcessorTests.java index b5b44d693cd..99969dadd9c 100644 --- a/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/MockitoPostProcessorTests.java +++ b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/MockitoPostProcessorTests.java @@ -74,7 +74,7 @@ class MockitoPostProcessorTests { } @Test - void canMockBeanProducedByFactoryBeanWithObjectTypeAttribute() { + void canMockBeanProducedByFactoryBeanWithStringObjectTypeAttribute() { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); MockitoPostProcessor.register(context); RootBeanDefinition factoryBeanDefinition = new RootBeanDefinition(TestFactoryBean.class); @@ -86,7 +86,7 @@ class MockitoPostProcessorTests { } @Test - void canMockBeanProducedByFactoryBeanWithClassAttribute() { + void canMockBeanProducedByFactoryBeanWithClassObjectTypeAttribute() { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); MockitoPostProcessor.register(context); RootBeanDefinition factoryBeanDefinition = new RootBeanDefinition(TestFactoryBean.class); @@ -98,7 +98,7 @@ class MockitoPostProcessorTests { } @Test - void canMockBeanProducedByFactoryBeanWithResolvableTypeAttribute() { + void canMockBeanProducedByFactoryBeanWithResolvableTypeObjectTypeAttribute() { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); MockitoPostProcessor.register(context); RootBeanDefinition factoryBeanDefinition = new RootBeanDefinition(TestFactoryBean.class);