From 6c2cba5d8ad29657a5164dd1ad369064f39660cf Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Wed, 18 Sep 2024 10:09:22 +0200 Subject: [PATCH] Polish bean override internals --- .../mockito/MockitoBeanOverrideMetadata.java | 44 +++++++++---------- .../bean/override/mockito/MockitoBeans.java | 11 ++--- .../mockito/MockitoOverrideMetadata.java | 32 ++++++++------ .../MockitoResetTestExecutionListener.java | 7 +-- .../MockitoSpyBeanOverrideMetadata.java | 13 +----- ...toBeanForByNameLookupIntegrationTests.java | 25 +++-------- 6 files changed, 54 insertions(+), 78 deletions(-) diff --git a/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockitoBeanOverrideMetadata.java b/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockitoBeanOverrideMetadata.java index 5167d6b9053f..cbb4505427b9 100644 --- a/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockitoBeanOverrideMetadata.java +++ b/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockitoBeanOverrideMetadata.java @@ -35,7 +35,6 @@ import org.springframework.test.context.bean.override.OverrideMetadata; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; -import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; /** @@ -43,13 +42,14 @@ * * @author Phillip Webb * @author Stephane Nicoll + * @author Sam Brannen * @since 6.2 */ class MockitoBeanOverrideMetadata extends MockitoOverrideMetadata { private final Set> extraInterfaces; - private final Answers answer; + private final Answers answers; private final boolean serializable; @@ -59,21 +59,22 @@ class MockitoBeanOverrideMetadata extends MockitoOverrideMetadata { annotation.reset(), annotation.extraInterfaces(), annotation.answers(), annotation.serializable()); } - MockitoBeanOverrideMetadata(Field field, ResolvableType typeToMock, @Nullable String beanName, MockReset reset, - Class[] extraInterfaces, @Nullable Answers answer, boolean serializable) { + private MockitoBeanOverrideMetadata(Field field, ResolvableType typeToMock, @Nullable String beanName, MockReset reset, + Class[] extraInterfaces, @Nullable Answers answers, boolean serializable) { super(field, typeToMock, beanName, BeanOverrideStrategy.REPLACE_OR_CREATE_DEFINITION, reset, false); Assert.notNull(typeToMock, "'typeToMock' must not be null"); this.extraInterfaces = asClassSet(extraInterfaces); - this.answer = (answer != null) ? answer : Answers.RETURNS_DEFAULTS; + this.answers = (answers != null ? answers : Answers.RETURNS_DEFAULTS); this.serializable = serializable; } - private static Set> asClassSet(@Nullable Class[] classes) { - Set> classSet = new LinkedHashSet<>(); - if (classes != null) { - classSet.addAll(Arrays.asList(classes)); + + private static Set> asClassSet(Class[] classes) { + if (classes.length == 0) { + return Collections.emptySet(); } + Set> classSet = new LinkedHashSet<>(Arrays.asList(classes)); return Collections.unmodifiableSet(classSet); } @@ -90,12 +91,12 @@ Set> getExtraInterfaces() { * Return the {@link Answers}. * @return the answers mode */ - Answers getAnswer() { - return this.answer; + Answers getAnswers() { + return this.answers; } /** - * Return if the mock is serializable. + * Determine if the mock is serializable. * @return {@code true} if the mock is serializable */ boolean isSerializable() { @@ -108,7 +109,7 @@ protected Object createOverride(String beanName, @Nullable BeanDefinition existi } @SuppressWarnings("unchecked") - T createMock(String name) { + private T createMock(String name) { MockSettings settings = MockReset.withSettings(getReset()); if (StringUtils.hasLength(name)) { settings.name(name); @@ -116,7 +117,7 @@ T createMock(String name) { if (!this.extraInterfaces.isEmpty()) { settings.extraInterfaces(ClassUtils.toClassArray(this.extraInterfaces)); } - settings.defaultAnswer(this.answer); + settings.defaultAnswer(this.answers); if (this.serializable) { settings.serializable(); } @@ -132,27 +133,26 @@ public boolean equals(@Nullable Object other) { if (other == null || other.getClass() != getClass()) { return false; } - MockitoBeanOverrideMetadata that = (MockitoBeanOverrideMetadata) other; - boolean result = super.equals(that); - result = result && ObjectUtils.nullSafeEquals(this.extraInterfaces, that.extraInterfaces); - result = result && ObjectUtils.nullSafeEquals(this.answer, that.answer); - result = result && this.serializable == that.serializable; - return result; + return (other instanceof MockitoBeanOverrideMetadata that && super.equals(that) && + (this.serializable == that.serializable) && (this.answers == that.answers) && + Objects.equals(this.extraInterfaces, that.extraInterfaces)); } @Override public int hashCode() { - return Objects.hash(this.extraInterfaces, this.answer, this.serializable) + super.hashCode(); + return super.hashCode() + Objects.hash(this.extraInterfaces, this.answers, this.serializable); } @Override public String toString() { return new ToStringCreator(this) + .append("field", getField()) .append("beanType", getBeanType()) .append("beanName", getBeanName()) + .append("strategy", getStrategy()) .append("reset", getReset()) .append("extraInterfaces", getExtraInterfaces()) - .append("answer", getAnswer()) + .append("answers", getAnswers()) .append("serializable", isSerializable()) .toString(); } diff --git a/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockitoBeans.java b/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockitoBeans.java index 3e5f3e4983d3..fce591812f9f 100644 --- a/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockitoBeans.java +++ b/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockitoBeans.java @@ -17,16 +17,18 @@ package org.springframework.test.context.bean.override.mockito; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; +import org.mockito.Mockito; + /** * Beans created using Mockito. * * @author Andy Wilkinson + * @author Sam Brannen * @since 6.2 */ -class MockitoBeans implements Iterable { +class MockitoBeans { private final List beans = new ArrayList<>(); @@ -35,9 +37,8 @@ void add(Object bean) { this.beans.add(bean); } - @Override - public Iterator iterator() { - return this.beans.iterator(); + void resetAll() { + this.beans.forEach(Mockito::reset); } } diff --git a/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockitoOverrideMetadata.java b/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockitoOverrideMetadata.java index 974966f00637..2ca61fc5ed40 100644 --- a/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockitoOverrideMetadata.java +++ b/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockitoOverrideMetadata.java @@ -22,16 +22,17 @@ import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.config.SingletonBeanRegistry; import org.springframework.core.ResolvableType; +import org.springframework.core.style.ToStringCreator; import org.springframework.lang.Nullable; import org.springframework.test.context.bean.override.BeanOverrideStrategy; import org.springframework.test.context.bean.override.OverrideMetadata; -import org.springframework.util.ObjectUtils; /** * Base {@link OverrideMetadata} implementation for Mockito. * * @author Phillip Webb * @author Stephane Nicoll + * @author Sam Brannen * @since 6.2 */ abstract class MockitoOverrideMetadata extends OverrideMetadata { @@ -45,7 +46,7 @@ protected MockitoOverrideMetadata(Field field, ResolvableType beanType, @Nullabl BeanOverrideStrategy strategy, @Nullable MockReset reset, boolean proxyTargetAware) { super(field, beanType, beanName, strategy); - this.reset = (reset != null) ? reset : MockReset.AFTER; + this.reset = (reset != null ? reset : MockReset.AFTER); this.proxyTargetAware = proxyTargetAware; } @@ -73,10 +74,9 @@ protected void track(Object mock, SingletonBeanRegistry trackingBeanRegistry) { tracker = (MockitoBeans) trackingBeanRegistry.getSingleton(MockitoBeans.class.getName()); } catch (NoSuchBeanDefinitionException ignored) { - } if (tracker == null) { - tracker= new MockitoBeans(); + tracker = new MockitoBeans(); trackingBeanRegistry.registerSingleton(MockitoBeans.class.getName(), tracker); } tracker.add(mock); @@ -87,19 +87,25 @@ public boolean equals(@Nullable Object other) { if (other == this) { return true; } - if (other == null || !getClass().isAssignableFrom(other.getClass())) { - return false; - } - MockitoOverrideMetadata that = (MockitoOverrideMetadata) other; - boolean result = super.equals(that); - result = result && ObjectUtils.nullSafeEquals(this.reset, that.reset); - result = result && ObjectUtils.nullSafeEquals(this.proxyTargetAware, that.proxyTargetAware); - return result; + return (other instanceof MockitoOverrideMetadata that && super.equals(that) && + (this.reset == that.reset) && (this.proxyTargetAware == that.proxyTargetAware)); } @Override public int hashCode() { - return Objects.hash(this.reset, this.proxyTargetAware) + super.hashCode(); + return super.hashCode() + Objects.hash(this.reset, this.proxyTargetAware); + } + + @Override + public String toString() { + return new ToStringCreator(this) + .append("field", getField()) + .append("beanType", getBeanType()) + .append("beanName", getBeanName()) + .append("strategy", getStrategy()) + .append("reset", getReset()) + .append("proxyTargetAware", isProxyTargetAware()) + .toString(); } } diff --git a/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockitoResetTestExecutionListener.java b/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockitoResetTestExecutionListener.java index e96107d3c6fa..bbf8f8182033 100644 --- a/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockitoResetTestExecutionListener.java +++ b/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockitoResetTestExecutionListener.java @@ -87,12 +87,7 @@ private void resetMocks(ConfigurableApplicationContext applicationContext, MockR } } try { - MockitoBeans mockedBeans = beanFactory.getBean(MockitoBeans.class); - for (Object mockedBean : mockedBeans) { - if (reset.equals(MockReset.get(mockedBean))) { - Mockito.reset(mockedBean); - } - } + beanFactory.getBean(MockitoBeans.class).resetAll(); } catch (NoSuchBeanDefinitionException ex) { // Continue diff --git a/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBeanOverrideMetadata.java b/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBeanOverrideMetadata.java index 6cf5a77e08a8..4a96d585743c 100644 --- a/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBeanOverrideMetadata.java +++ b/spring-test/src/main/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBeanOverrideMetadata.java @@ -27,7 +27,6 @@ import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.core.ResolvableType; -import org.springframework.core.style.ToStringCreator; import org.springframework.lang.Nullable; import org.springframework.test.context.bean.override.BeanOverrideStrategy; import org.springframework.test.context.bean.override.OverrideMetadata; @@ -68,8 +67,7 @@ protected Object createOverride(String beanName, @Nullable BeanDefinition existi } @SuppressWarnings("unchecked") - T createSpy(String name, Object instance) { - Assert.notNull(instance, "Instance must not be null"); + private T createSpy(String name, Object instance) { Class resolvedTypeToOverride = getBeanType().resolve(); Assert.notNull(resolvedTypeToOverride, "Failed to resolve type to override"); Assert.isInstanceOf(resolvedTypeToOverride, instance); @@ -96,15 +94,6 @@ T createSpy(String name, Object instance) { return (T) Mockito.mock(toSpy, settings); } - @Override - public String toString() { - return new ToStringCreator(this) - .append("beanName", getBeanName()) - .append("beanType", getBeanType()) - .append("reset", getReset()) - .toString(); - } - /** * A {@link VerificationStartedListener} that bypasses any proxy created by 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 7f3324efbadb..d2d225309627 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 @@ -56,22 +56,14 @@ public class MockitoBeanForByNameLookupIntegrationTests { @Test - void fieldHasOverride(ApplicationContext ctx) { - assertThat(ctx.getBean("field")) - .isInstanceOf(ExampleService.class) - .satisfies(o -> assertThat(Mockito.mockingDetails(o).isMock()).as("isMock").isTrue()) - .isSameAs(this.field); - - assertThat(this.field.greeting()).as("mocked greeting").isNull(); - } - - @Test - void renamedFieldHasOverride(ApplicationContext ctx) { + void fieldAndRenamedFieldHaveSameOverride(ApplicationContext ctx) { assertThat(ctx.getBean("field")) .isInstanceOf(ExampleService.class) .satisfies(o -> assertThat(Mockito.mockingDetails(o).isMock()).as("isMock").isTrue()) + .isSameAs(this.field) .isSameAs(this.renamed1); + assertThat(this.field.greeting()).as("mocked greeting").isNull(); assertThat(this.renamed1.greeting()).as("mocked greeting").isNull(); } @@ -91,18 +83,11 @@ void fieldIsMockedWhenNoOriginalBean(ApplicationContext ctx) { public class MockitoBeanNestedTests { @Test - void fieldHasOverride(ApplicationContext ctx) { - assertThat(ctx.getBean("nestedField")) - .isInstanceOf(ExampleService.class) - .satisfies(o -> assertThat(Mockito.mockingDetails(o).isMock()).as("isMock").isTrue()) - .isSameAs(nestedField); - } - - @Test - void renamedFieldHasOverride(ApplicationContext ctx) { + void fieldAndRenamedFieldHaveSameOverride(ApplicationContext ctx) { assertThat(ctx.getBean("nestedField")) .isInstanceOf(ExampleService.class) .satisfies(o -> assertThat(Mockito.mockingDetails(o).isMock()).as("isMock").isTrue()) + .isSameAs(nestedField) .isSameAs(renamed2); }