Harmonize OverrideMetadata implementations
This commit makes sure that each OverrideMetadata implementation is a top level class with a consistent name.
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright 2002-2024 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.convention;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.core.ResolvableType;
|
||||
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.ReflectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* {@link OverrideMetadata} implementation for {@link TestBean}.
|
||||
*
|
||||
* @author Simon Baslé
|
||||
* @author Stephane Nicoll
|
||||
* @since 6.2
|
||||
*/
|
||||
final class TestBeanOverrideMetadata extends OverrideMetadata {
|
||||
|
||||
private final Method overrideMethod;
|
||||
|
||||
private final String beanName;
|
||||
|
||||
TestBeanOverrideMetadata(Field field, Method overrideMethod, TestBean overrideAnnotation,
|
||||
ResolvableType typeToOverride) {
|
||||
|
||||
super(field, typeToOverride, BeanOverrideStrategy.REPLACE_DEFINITION);
|
||||
this.beanName = overrideAnnotation.name();
|
||||
this.overrideMethod = overrideMethod;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected String getBeanName() {
|
||||
return StringUtils.hasText(this.beanName) ? this.beanName : super.getBeanName();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object createOverride(String beanName, @Nullable BeanDefinition existingBeanDefinition,
|
||||
@Nullable Object existingBeanInstance) {
|
||||
|
||||
try {
|
||||
ReflectionUtils.makeAccessible(this.overrideMethod);
|
||||
return this.overrideMethod.invoke(null);
|
||||
}
|
||||
catch (IllegalAccessException | InvocationTargetException ex) {
|
||||
throw new IllegalStateException("Failed to invoke bean overriding method " + this.overrideMethod.getName() +
|
||||
"; a static method with no formal parameters is expected", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
if (!super.equals(o)) {
|
||||
return false;
|
||||
}
|
||||
TestBeanOverrideMetadata that = (TestBeanOverrideMetadata) o;
|
||||
return Objects.equals(this.overrideMethod, that.overrideMethod)
|
||||
&& Objects.equals(this.beanName, that.beanName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(super.hashCode(), this.overrideMethod, this.beanName);
|
||||
}
|
||||
}
|
||||
@@ -18,25 +18,18 @@ package org.springframework.test.context.bean.override.convention;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.core.MethodIntrospector;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.test.context.TestContextAnnotationUtils;
|
||||
import org.springframework.test.context.bean.override.BeanOverrideProcessor;
|
||||
import org.springframework.test.context.bean.override.BeanOverrideStrategy;
|
||||
import org.springframework.test.context.bean.override.OverrideMetadata;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.ReflectionUtils.MethodFilter;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@@ -143,61 +136,4 @@ class TestBeanOverrideProcessor implements BeanOverrideProcessor {
|
||||
return methods;
|
||||
}
|
||||
|
||||
|
||||
static final class TestBeanOverrideMetadata extends OverrideMetadata {
|
||||
|
||||
private final Method overrideMethod;
|
||||
|
||||
private final String beanName;
|
||||
|
||||
public TestBeanOverrideMetadata(Field field, Method overrideMethod, TestBean overrideAnnotation,
|
||||
ResolvableType typeToOverride) {
|
||||
|
||||
super(field, typeToOverride, BeanOverrideStrategy.REPLACE_DEFINITION);
|
||||
this.beanName = overrideAnnotation.name();
|
||||
this.overrideMethod = overrideMethod;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected String getBeanName() {
|
||||
return StringUtils.hasText(this.beanName) ? this.beanName : super.getBeanName();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object createOverride(String beanName, @Nullable BeanDefinition existingBeanDefinition,
|
||||
@Nullable Object existingBeanInstance) {
|
||||
|
||||
try {
|
||||
ReflectionUtils.makeAccessible(this.overrideMethod);
|
||||
return this.overrideMethod.invoke(null);
|
||||
}
|
||||
catch (IllegalAccessException | InvocationTargetException ex) {
|
||||
throw new IllegalStateException("Failed to invoke bean overriding method " + this.overrideMethod.getName() +
|
||||
"; a static method with no formal parameters is expected", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
if (!super.equals(o)) {
|
||||
return false;
|
||||
}
|
||||
TestBeanOverrideMetadata that = (TestBeanOverrideMetadata) o;
|
||||
return Objects.equals(this.overrideMethod, that.overrideMethod)
|
||||
&& Objects.equals(this.beanName, that.beanName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(super.hashCode(), this.overrideMethod, this.beanName);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2024 the original author or authors.
|
||||
* Copyright 2002-2024 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.
|
||||
@@ -31,6 +31,7 @@ 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.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
@@ -39,12 +40,12 @@ import org.springframework.util.StringUtils;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* A complete definition that can be used to create a Mockito mock.
|
||||
* {@link OverrideMetadata} implementation for Mockito {@code mock} support.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @since 6.2
|
||||
*/
|
||||
class MockitoBeanMetadata extends MockitoMetadata {
|
||||
class MockitoBeanOverrideMetadata extends MockitoOverrideMetadata {
|
||||
|
||||
private final Set<Class<?>> extraInterfaces;
|
||||
|
||||
@@ -53,12 +54,12 @@ class MockitoBeanMetadata extends MockitoMetadata {
|
||||
private final boolean serializable;
|
||||
|
||||
|
||||
MockitoBeanMetadata(MockitoBean annotation, Field field, ResolvableType typeToMock) {
|
||||
MockitoBeanOverrideMetadata(MockitoBean annotation, Field field, ResolvableType typeToMock) {
|
||||
this(annotation.name(), annotation.reset(), field, typeToMock,
|
||||
annotation.extraInterfaces(), annotation.answers(), annotation.serializable());
|
||||
}
|
||||
|
||||
MockitoBeanMetadata(String name, MockReset reset, Field field, ResolvableType typeToMock,
|
||||
MockitoBeanOverrideMetadata(String name, MockReset reset, Field field, ResolvableType typeToMock,
|
||||
Class<?>[] extraInterfaces, @Nullable Answers answer, boolean serializable) {
|
||||
|
||||
super(name, reset, false, field, typeToMock, BeanOverrideStrategy.REPLACE_OR_CREATE_DEFINITION);
|
||||
@@ -68,18 +69,6 @@ class MockitoBeanMetadata extends MockitoMetadata {
|
||||
this.serializable = serializable;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object createOverride(String beanName, @Nullable BeanDefinition existingBeanDefinition, @Nullable Object existingBeanInstance) {
|
||||
return createMock(beanName);
|
||||
}
|
||||
|
||||
private Set<Class<?>> asClassSet(@Nullable Class<?>[] classes) {
|
||||
Set<Class<?>> classSet = new LinkedHashSet<>();
|
||||
if (classes != null) {
|
||||
classSet.addAll(Arrays.asList(classes));
|
||||
}
|
||||
return Collections.unmodifiableSet(classSet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the extra interfaces.
|
||||
@@ -105,6 +94,19 @@ class MockitoBeanMetadata extends MockitoMetadata {
|
||||
return this.serializable;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object createOverride(String beanName, @Nullable BeanDefinition existingBeanDefinition, @Nullable Object existingBeanInstance) {
|
||||
return createMock(beanName);
|
||||
}
|
||||
|
||||
private Set<Class<?>> asClassSet(@Nullable Class<?>[] classes) {
|
||||
Set<Class<?>> classSet = new LinkedHashSet<>();
|
||||
if (classes != null) {
|
||||
classSet.addAll(Arrays.asList(classes));
|
||||
}
|
||||
return Collections.unmodifiableSet(classSet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
if (obj == this) {
|
||||
@@ -113,7 +115,7 @@ class MockitoBeanMetadata extends MockitoMetadata {
|
||||
if (obj == null || obj.getClass() != getClass()) {
|
||||
return false;
|
||||
}
|
||||
MockitoBeanMetadata other = (MockitoBeanMetadata) obj;
|
||||
MockitoBeanOverrideMetadata other = (MockitoBeanOverrideMetadata) obj;
|
||||
boolean result = super.equals(obj);
|
||||
result = result && ObjectUtils.nullSafeEquals(this.extraInterfaces, other.extraInterfaces);
|
||||
result = result && ObjectUtils.nullSafeEquals(this.answer, other.answer);
|
||||
@@ -34,12 +34,12 @@ import org.springframework.test.context.bean.override.BeanOverrideProcessor;
|
||||
class MockitoBeanOverrideProcessor implements BeanOverrideProcessor {
|
||||
|
||||
@Override
|
||||
public MockitoMetadata createMetadata(Annotation overrideAnnotation, Class<?> testClass, Field field) {
|
||||
public MockitoOverrideMetadata createMetadata(Annotation overrideAnnotation, Class<?> testClass, Field field) {
|
||||
if (overrideAnnotation instanceof MockitoBean mockBean) {
|
||||
return new MockitoBeanMetadata(mockBean, field, ResolvableType.forField(field, testClass));
|
||||
return new MockitoBeanOverrideMetadata(mockBean, field, ResolvableType.forField(field, testClass));
|
||||
}
|
||||
else if (overrideAnnotation instanceof MockitoSpyBean spyBean) {
|
||||
return new MockitoSpyBeanMetadata(spyBean, field, ResolvableType.forField(field, testClass));
|
||||
return new MockitoSpyBeanOverrideMetadata(spyBean, field, ResolvableType.forField(field, testClass));
|
||||
}
|
||||
throw new IllegalStateException(String.format("Invalid annotation passed to MockitoBeanOverrideProcessor: "
|
||||
+ "expected @MockitoBean/@MockitoSpyBean on field %s.%s",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2024 the original author or authors.
|
||||
* Copyright 2002-2024 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.
|
||||
@@ -29,12 +29,12 @@ import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Base class for Mockito override metadata.
|
||||
* Base {@link OverrideMetadata} implementation for Mockito.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @since 6.2
|
||||
*/
|
||||
abstract class MockitoMetadata extends OverrideMetadata {
|
||||
abstract class MockitoOverrideMetadata extends OverrideMetadata {
|
||||
|
||||
protected final String name;
|
||||
|
||||
@@ -43,7 +43,7 @@ abstract class MockitoMetadata extends OverrideMetadata {
|
||||
private final boolean proxyTargetAware;
|
||||
|
||||
|
||||
MockitoMetadata(String name, @Nullable MockReset reset, boolean proxyTargetAware, Field field,
|
||||
MockitoOverrideMetadata(String name, @Nullable MockReset reset, boolean proxyTargetAware, Field field,
|
||||
ResolvableType typeToOverride, BeanOverrideStrategy strategy) {
|
||||
|
||||
super(field, typeToOverride, strategy);
|
||||
@@ -59,22 +59,6 @@ abstract class MockitoMetadata extends OverrideMetadata {
|
||||
return StringUtils.hasText(this.name) ? this.name : super.getBeanName();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void track(Object mock, SingletonBeanRegistry trackingBeanRegistry) {
|
||||
MockitoBeans tracker = null;
|
||||
try {
|
||||
tracker = (MockitoBeans) trackingBeanRegistry.getSingleton(MockitoBeans.class.getName());
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException ignored) {
|
||||
|
||||
}
|
||||
if (tracker == null) {
|
||||
tracker= new MockitoBeans();
|
||||
trackingBeanRegistry.registerSingleton(MockitoBeans.class.getName(), tracker);
|
||||
}
|
||||
tracker.add(mock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the mock reset mode.
|
||||
* @return the reset mode
|
||||
@@ -91,6 +75,22 @@ abstract class MockitoMetadata extends OverrideMetadata {
|
||||
return this.proxyTargetAware;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void track(Object mock, SingletonBeanRegistry trackingBeanRegistry) {
|
||||
MockitoBeans tracker = null;
|
||||
try {
|
||||
tracker = (MockitoBeans) trackingBeanRegistry.getSingleton(MockitoBeans.class.getName());
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException ignored) {
|
||||
|
||||
}
|
||||
if (tracker == null) {
|
||||
tracker= new MockitoBeans();
|
||||
trackingBeanRegistry.registerSingleton(MockitoBeans.class.getName(), tracker);
|
||||
}
|
||||
tracker.add(mock);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
if (obj == this) {
|
||||
@@ -99,7 +99,7 @@ abstract class MockitoMetadata extends OverrideMetadata {
|
||||
if (obj == null || !getClass().isAssignableFrom(obj.getClass())) {
|
||||
return false;
|
||||
}
|
||||
MockitoMetadata other = (MockitoMetadata) obj;
|
||||
MockitoOverrideMetadata other = (MockitoOverrideMetadata) obj;
|
||||
boolean result = super.equals(obj);
|
||||
result = result && ObjectUtils.nullSafeEquals(this.name, other.name);
|
||||
result = result && ObjectUtils.nullSafeEquals(this.reset, other.reset);
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2024 the original author or authors.
|
||||
* Copyright 2002-2024 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.
|
||||
@@ -40,20 +40,20 @@ import org.springframework.util.StringUtils;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* {@link OverrideMetadata} for Mockito {@code spy} support.
|
||||
* {@link OverrideMetadata} implementation for Mockito {@code spy} support.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Simon Baslé
|
||||
* @since 6.2
|
||||
*/
|
||||
class MockitoSpyBeanMetadata extends MockitoMetadata {
|
||||
class MockitoSpyBeanOverrideMetadata extends MockitoOverrideMetadata {
|
||||
|
||||
MockitoSpyBeanMetadata(MockitoSpyBean spyAnnotation, Field field, ResolvableType typeToSpy) {
|
||||
MockitoSpyBeanOverrideMetadata(MockitoSpyBean spyAnnotation, Field field, ResolvableType typeToSpy) {
|
||||
this(spyAnnotation.name(), spyAnnotation.reset(), spyAnnotation.proxyTargetAware(),
|
||||
field, typeToSpy);
|
||||
}
|
||||
|
||||
MockitoSpyBeanMetadata(String name, MockReset reset, boolean proxyTargetAware, Field field, ResolvableType typeToSpy) {
|
||||
MockitoSpyBeanOverrideMetadata(String name, MockReset reset, boolean proxyTargetAware, Field field, ResolvableType typeToSpy) {
|
||||
super(name, reset, proxyTargetAware, field, typeToSpy, BeanOverrideStrategy.WRAP_BEAN);
|
||||
Assert.notNull(typeToSpy, "typeToSpy must not be null");
|
||||
}
|
||||
@@ -68,33 +68,6 @@ class MockitoSpyBeanMetadata extends MockitoMetadata {
|
||||
return createSpy(beanName, existingBeanInstance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
// For SpyBean we want the class to be exactly the same.
|
||||
if (obj == null || obj.getClass() != getClass()) {
|
||||
return false;
|
||||
}
|
||||
MockitoSpyBeanMetadata that = (MockitoSpyBeanMetadata) obj;
|
||||
return (super.equals(obj) && ObjectUtils.nullSafeEquals(getBeanType(), that.getBeanType()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(super.hashCode(), getBeanType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringCreator(this)
|
||||
.append("beanName", getBeanName())
|
||||
.append("beanType", getBeanType())
|
||||
.append("reset", getReset())
|
||||
.toString();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
<T> T createSpy(String name, Object instance) {
|
||||
Assert.notNull(instance, "Instance must not be null");
|
||||
@@ -124,6 +97,34 @@ class MockitoSpyBeanMetadata extends MockitoMetadata {
|
||||
return (T) mock(toSpy, settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
// For SpyBean we want the class to be exactly the same.
|
||||
if (obj == null || obj.getClass() != getClass()) {
|
||||
return false;
|
||||
}
|
||||
MockitoSpyBeanOverrideMetadata that = (MockitoSpyBeanOverrideMetadata) obj;
|
||||
return (super.equals(obj) && ObjectUtils.nullSafeEquals(getBeanType(), that.getBeanType()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(super.hashCode(), getBeanType());
|
||||
}
|
||||
|
||||
@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
|
||||
* Spring AOP when the verification of a spy starts.
|
||||
@@ -134,7 +135,6 @@ class MockitoSpyBeanMetadata extends MockitoMetadata {
|
||||
public void onVerificationStarted(VerificationStartedEvent event) {
|
||||
event.setMock(AopTestUtils.getUltimateTargetObject(event.getMock()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user