Polish bean override internals
This commit is contained in:
parent
c832d5f496
commit
6c2cba5d8a
|
@ -35,7 +35,6 @@ import org.springframework.test.context.bean.override.BeanOverrideStrategy;
|
||||||
import org.springframework.test.context.bean.override.OverrideMetadata;
|
import org.springframework.test.context.bean.override.OverrideMetadata;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.ClassUtils;
|
import org.springframework.util.ClassUtils;
|
||||||
import org.springframework.util.ObjectUtils;
|
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -43,13 +42,14 @@ import org.springframework.util.StringUtils;
|
||||||
*
|
*
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
|
* @author Sam Brannen
|
||||||
* @since 6.2
|
* @since 6.2
|
||||||
*/
|
*/
|
||||||
class MockitoBeanOverrideMetadata extends MockitoOverrideMetadata {
|
class MockitoBeanOverrideMetadata extends MockitoOverrideMetadata {
|
||||||
|
|
||||||
private final Set<Class<?>> extraInterfaces;
|
private final Set<Class<?>> extraInterfaces;
|
||||||
|
|
||||||
private final Answers answer;
|
private final Answers answers;
|
||||||
|
|
||||||
private final boolean serializable;
|
private final boolean serializable;
|
||||||
|
|
||||||
|
@ -59,21 +59,22 @@ class MockitoBeanOverrideMetadata extends MockitoOverrideMetadata {
|
||||||
annotation.reset(), annotation.extraInterfaces(), annotation.answers(), annotation.serializable());
|
annotation.reset(), annotation.extraInterfaces(), annotation.answers(), annotation.serializable());
|
||||||
}
|
}
|
||||||
|
|
||||||
MockitoBeanOverrideMetadata(Field field, ResolvableType typeToMock, @Nullable String beanName, MockReset reset,
|
private MockitoBeanOverrideMetadata(Field field, ResolvableType typeToMock, @Nullable String beanName, MockReset reset,
|
||||||
Class<?>[] extraInterfaces, @Nullable Answers answer, boolean serializable) {
|
Class<?>[] extraInterfaces, @Nullable Answers answers, boolean serializable) {
|
||||||
|
|
||||||
super(field, typeToMock, beanName, BeanOverrideStrategy.REPLACE_OR_CREATE_DEFINITION, reset, false);
|
super(field, typeToMock, beanName, BeanOverrideStrategy.REPLACE_OR_CREATE_DEFINITION, reset, false);
|
||||||
Assert.notNull(typeToMock, "'typeToMock' must not be null");
|
Assert.notNull(typeToMock, "'typeToMock' must not be null");
|
||||||
this.extraInterfaces = asClassSet(extraInterfaces);
|
this.extraInterfaces = asClassSet(extraInterfaces);
|
||||||
this.answer = (answer != null) ? answer : Answers.RETURNS_DEFAULTS;
|
this.answers = (answers != null ? answers : Answers.RETURNS_DEFAULTS);
|
||||||
this.serializable = serializable;
|
this.serializable = serializable;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Set<Class<?>> asClassSet(@Nullable Class<?>[] classes) {
|
|
||||||
Set<Class<?>> classSet = new LinkedHashSet<>();
|
private static Set<Class<?>> asClassSet(Class<?>[] classes) {
|
||||||
if (classes != null) {
|
if (classes.length == 0) {
|
||||||
classSet.addAll(Arrays.asList(classes));
|
return Collections.emptySet();
|
||||||
}
|
}
|
||||||
|
Set<Class<?>> classSet = new LinkedHashSet<>(Arrays.asList(classes));
|
||||||
return Collections.unmodifiableSet(classSet);
|
return Collections.unmodifiableSet(classSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,12 +91,12 @@ class MockitoBeanOverrideMetadata extends MockitoOverrideMetadata {
|
||||||
* Return the {@link Answers}.
|
* Return the {@link Answers}.
|
||||||
* @return the answers mode
|
* @return the answers mode
|
||||||
*/
|
*/
|
||||||
Answers getAnswer() {
|
Answers getAnswers() {
|
||||||
return this.answer;
|
return this.answers;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return if the mock is serializable.
|
* Determine if the mock is serializable.
|
||||||
* @return {@code true} if the mock is serializable
|
* @return {@code true} if the mock is serializable
|
||||||
*/
|
*/
|
||||||
boolean isSerializable() {
|
boolean isSerializable() {
|
||||||
|
@ -108,7 +109,7 @@ class MockitoBeanOverrideMetadata extends MockitoOverrideMetadata {
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
<T> T createMock(String name) {
|
private <T> T createMock(String name) {
|
||||||
MockSettings settings = MockReset.withSettings(getReset());
|
MockSettings settings = MockReset.withSettings(getReset());
|
||||||
if (StringUtils.hasLength(name)) {
|
if (StringUtils.hasLength(name)) {
|
||||||
settings.name(name);
|
settings.name(name);
|
||||||
|
@ -116,7 +117,7 @@ class MockitoBeanOverrideMetadata extends MockitoOverrideMetadata {
|
||||||
if (!this.extraInterfaces.isEmpty()) {
|
if (!this.extraInterfaces.isEmpty()) {
|
||||||
settings.extraInterfaces(ClassUtils.toClassArray(this.extraInterfaces));
|
settings.extraInterfaces(ClassUtils.toClassArray(this.extraInterfaces));
|
||||||
}
|
}
|
||||||
settings.defaultAnswer(this.answer);
|
settings.defaultAnswer(this.answers);
|
||||||
if (this.serializable) {
|
if (this.serializable) {
|
||||||
settings.serializable();
|
settings.serializable();
|
||||||
}
|
}
|
||||||
|
@ -132,27 +133,26 @@ class MockitoBeanOverrideMetadata extends MockitoOverrideMetadata {
|
||||||
if (other == null || other.getClass() != getClass()) {
|
if (other == null || other.getClass() != getClass()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
MockitoBeanOverrideMetadata that = (MockitoBeanOverrideMetadata) other;
|
return (other instanceof MockitoBeanOverrideMetadata that && super.equals(that) &&
|
||||||
boolean result = super.equals(that);
|
(this.serializable == that.serializable) && (this.answers == that.answers) &&
|
||||||
result = result && ObjectUtils.nullSafeEquals(this.extraInterfaces, that.extraInterfaces);
|
Objects.equals(this.extraInterfaces, that.extraInterfaces));
|
||||||
result = result && ObjectUtils.nullSafeEquals(this.answer, that.answer);
|
|
||||||
result = result && this.serializable == that.serializable;
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
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
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return new ToStringCreator(this)
|
return new ToStringCreator(this)
|
||||||
|
.append("field", getField())
|
||||||
.append("beanType", getBeanType())
|
.append("beanType", getBeanType())
|
||||||
.append("beanName", getBeanName())
|
.append("beanName", getBeanName())
|
||||||
|
.append("strategy", getStrategy())
|
||||||
.append("reset", getReset())
|
.append("reset", getReset())
|
||||||
.append("extraInterfaces", getExtraInterfaces())
|
.append("extraInterfaces", getExtraInterfaces())
|
||||||
.append("answer", getAnswer())
|
.append("answers", getAnswers())
|
||||||
.append("serializable", isSerializable())
|
.append("serializable", isSerializable())
|
||||||
.toString();
|
.toString();
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,16 +17,18 @@
|
||||||
package org.springframework.test.context.bean.override.mockito;
|
package org.springframework.test.context.bean.override.mockito;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Beans created using Mockito.
|
* Beans created using Mockito.
|
||||||
*
|
*
|
||||||
* @author Andy Wilkinson
|
* @author Andy Wilkinson
|
||||||
|
* @author Sam Brannen
|
||||||
* @since 6.2
|
* @since 6.2
|
||||||
*/
|
*/
|
||||||
class MockitoBeans implements Iterable<Object> {
|
class MockitoBeans {
|
||||||
|
|
||||||
private final List<Object> beans = new ArrayList<>();
|
private final List<Object> beans = new ArrayList<>();
|
||||||
|
|
||||||
|
@ -35,9 +37,8 @@ class MockitoBeans implements Iterable<Object> {
|
||||||
this.beans.add(bean);
|
this.beans.add(bean);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
void resetAll() {
|
||||||
public Iterator<Object> iterator() {
|
this.beans.forEach(Mockito::reset);
|
||||||
return this.beans.iterator();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,16 +22,17 @@ import java.util.Objects;
|
||||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||||
import org.springframework.beans.factory.config.SingletonBeanRegistry;
|
import org.springframework.beans.factory.config.SingletonBeanRegistry;
|
||||||
import org.springframework.core.ResolvableType;
|
import org.springframework.core.ResolvableType;
|
||||||
|
import org.springframework.core.style.ToStringCreator;
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.test.context.bean.override.BeanOverrideStrategy;
|
import org.springframework.test.context.bean.override.BeanOverrideStrategy;
|
||||||
import org.springframework.test.context.bean.override.OverrideMetadata;
|
import org.springframework.test.context.bean.override.OverrideMetadata;
|
||||||
import org.springframework.util.ObjectUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base {@link OverrideMetadata} implementation for Mockito.
|
* Base {@link OverrideMetadata} implementation for Mockito.
|
||||||
*
|
*
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
|
* @author Sam Brannen
|
||||||
* @since 6.2
|
* @since 6.2
|
||||||
*/
|
*/
|
||||||
abstract class MockitoOverrideMetadata extends OverrideMetadata {
|
abstract class MockitoOverrideMetadata extends OverrideMetadata {
|
||||||
|
@ -45,7 +46,7 @@ abstract class MockitoOverrideMetadata extends OverrideMetadata {
|
||||||
BeanOverrideStrategy strategy, @Nullable MockReset reset, boolean proxyTargetAware) {
|
BeanOverrideStrategy strategy, @Nullable MockReset reset, boolean proxyTargetAware) {
|
||||||
|
|
||||||
super(field, beanType, beanName, strategy);
|
super(field, beanType, beanName, strategy);
|
||||||
this.reset = (reset != null) ? reset : MockReset.AFTER;
|
this.reset = (reset != null ? reset : MockReset.AFTER);
|
||||||
this.proxyTargetAware = proxyTargetAware;
|
this.proxyTargetAware = proxyTargetAware;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,10 +74,9 @@ abstract class MockitoOverrideMetadata extends OverrideMetadata {
|
||||||
tracker = (MockitoBeans) trackingBeanRegistry.getSingleton(MockitoBeans.class.getName());
|
tracker = (MockitoBeans) trackingBeanRegistry.getSingleton(MockitoBeans.class.getName());
|
||||||
}
|
}
|
||||||
catch (NoSuchBeanDefinitionException ignored) {
|
catch (NoSuchBeanDefinitionException ignored) {
|
||||||
|
|
||||||
}
|
}
|
||||||
if (tracker == null) {
|
if (tracker == null) {
|
||||||
tracker= new MockitoBeans();
|
tracker = new MockitoBeans();
|
||||||
trackingBeanRegistry.registerSingleton(MockitoBeans.class.getName(), tracker);
|
trackingBeanRegistry.registerSingleton(MockitoBeans.class.getName(), tracker);
|
||||||
}
|
}
|
||||||
tracker.add(mock);
|
tracker.add(mock);
|
||||||
|
@ -87,19 +87,25 @@ abstract class MockitoOverrideMetadata extends OverrideMetadata {
|
||||||
if (other == this) {
|
if (other == this) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (other == null || !getClass().isAssignableFrom(other.getClass())) {
|
return (other instanceof MockitoOverrideMetadata that && super.equals(that) &&
|
||||||
return false;
|
(this.reset == that.reset) && (this.proxyTargetAware == that.proxyTargetAware));
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,12 +87,7 @@ public class MockitoResetTestExecutionListener extends AbstractTestExecutionList
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
MockitoBeans mockedBeans = beanFactory.getBean(MockitoBeans.class);
|
beanFactory.getBean(MockitoBeans.class).resetAll();
|
||||||
for (Object mockedBean : mockedBeans) {
|
|
||||||
if (reset.equals(MockReset.get(mockedBean))) {
|
|
||||||
Mockito.reset(mockedBean);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (NoSuchBeanDefinitionException ex) {
|
catch (NoSuchBeanDefinitionException ex) {
|
||||||
// Continue
|
// Continue
|
||||||
|
|
|
@ -27,7 +27,6 @@ import org.mockito.listeners.VerificationStartedListener;
|
||||||
|
|
||||||
import org.springframework.beans.factory.config.BeanDefinition;
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
import org.springframework.core.ResolvableType;
|
import org.springframework.core.ResolvableType;
|
||||||
import org.springframework.core.style.ToStringCreator;
|
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.test.context.bean.override.BeanOverrideStrategy;
|
import org.springframework.test.context.bean.override.BeanOverrideStrategy;
|
||||||
import org.springframework.test.context.bean.override.OverrideMetadata;
|
import org.springframework.test.context.bean.override.OverrideMetadata;
|
||||||
|
@ -68,8 +67,7 @@ class MockitoSpyBeanOverrideMetadata extends MockitoOverrideMetadata {
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
<T> T createSpy(String name, Object instance) {
|
private <T> T createSpy(String name, Object instance) {
|
||||||
Assert.notNull(instance, "Instance must not be null");
|
|
||||||
Class<?> resolvedTypeToOverride = getBeanType().resolve();
|
Class<?> resolvedTypeToOverride = getBeanType().resolve();
|
||||||
Assert.notNull(resolvedTypeToOverride, "Failed to resolve type to override");
|
Assert.notNull(resolvedTypeToOverride, "Failed to resolve type to override");
|
||||||
Assert.isInstanceOf(resolvedTypeToOverride, instance);
|
Assert.isInstanceOf(resolvedTypeToOverride, instance);
|
||||||
|
@ -96,15 +94,6 @@ class MockitoSpyBeanOverrideMetadata extends MockitoOverrideMetadata {
|
||||||
return (T) Mockito.mock(toSpy, settings);
|
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
|
* A {@link VerificationStartedListener} that bypasses any proxy created by
|
||||||
|
|
|
@ -56,22 +56,14 @@ public class MockitoBeanForByNameLookupIntegrationTests {
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void fieldHasOverride(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);
|
|
||||||
|
|
||||||
assertThat(this.field.greeting()).as("mocked greeting").isNull();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void renamedFieldHasOverride(ApplicationContext ctx) {
|
|
||||||
assertThat(ctx.getBean("field"))
|
assertThat(ctx.getBean("field"))
|
||||||
.isInstanceOf(ExampleService.class)
|
.isInstanceOf(ExampleService.class)
|
||||||
.satisfies(o -> assertThat(Mockito.mockingDetails(o).isMock()).as("isMock").isTrue())
|
.satisfies(o -> assertThat(Mockito.mockingDetails(o).isMock()).as("isMock").isTrue())
|
||||||
|
.isSameAs(this.field)
|
||||||
.isSameAs(this.renamed1);
|
.isSameAs(this.renamed1);
|
||||||
|
|
||||||
|
assertThat(this.field.greeting()).as("mocked greeting").isNull();
|
||||||
assertThat(this.renamed1.greeting()).as("mocked greeting").isNull();
|
assertThat(this.renamed1.greeting()).as("mocked greeting").isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,18 +83,11 @@ public class MockitoBeanForByNameLookupIntegrationTests {
|
||||||
public class MockitoBeanNestedTests {
|
public class MockitoBeanNestedTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void fieldHasOverride(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);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void renamedFieldHasOverride(ApplicationContext ctx) {
|
|
||||||
assertThat(ctx.getBean("nestedField"))
|
assertThat(ctx.getBean("nestedField"))
|
||||||
.isInstanceOf(ExampleService.class)
|
.isInstanceOf(ExampleService.class)
|
||||||
.satisfies(o -> assertThat(Mockito.mockingDetails(o).isMock()).as("isMock").isTrue())
|
.satisfies(o -> assertThat(Mockito.mockingDetails(o).isMock()).as("isMock").isTrue())
|
||||||
|
.isSameAs(nestedField)
|
||||||
.isSameAs(renamed2);
|
.isSameAs(renamed2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue