|
|
|
@ -17,9 +17,11 @@ |
|
|
|
package org.springframework.test.context.bean.override.mockito; |
|
|
|
package org.springframework.test.context.bean.override.mockito; |
|
|
|
|
|
|
|
|
|
|
|
import java.lang.annotation.Annotation; |
|
|
|
import java.lang.annotation.Annotation; |
|
|
|
import java.lang.reflect.Field; |
|
|
|
import java.lang.reflect.AnnotatedElement; |
|
|
|
import java.util.LinkedHashSet; |
|
|
|
import java.util.Arrays; |
|
|
|
|
|
|
|
import java.util.HashSet; |
|
|
|
import java.util.Set; |
|
|
|
import java.util.Set; |
|
|
|
|
|
|
|
import java.util.function.Predicate; |
|
|
|
|
|
|
|
|
|
|
|
import org.mockito.Mockito; |
|
|
|
import org.mockito.Mockito; |
|
|
|
import org.mockito.MockitoSession; |
|
|
|
import org.mockito.MockitoSession; |
|
|
|
@ -31,7 +33,6 @@ import org.springframework.test.context.support.AbstractTestExecutionListener; |
|
|
|
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener; |
|
|
|
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener; |
|
|
|
import org.springframework.util.ClassUtils; |
|
|
|
import org.springframework.util.ClassUtils; |
|
|
|
import org.springframework.util.ReflectionUtils; |
|
|
|
import org.springframework.util.ReflectionUtils; |
|
|
|
import org.springframework.util.ReflectionUtils.FieldCallback; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* {@code TestExecutionListener} that enables {@link MockitoBean @MockitoBean} |
|
|
|
* {@code TestExecutionListener} that enables {@link MockitoBean @MockitoBean} |
|
|
|
@ -41,7 +42,7 @@ import org.springframework.util.ReflectionUtils.FieldCallback; |
|
|
|
* |
|
|
|
* |
|
|
|
* <p>The {@link MockitoSession#setStrictness(Strictness) strictness} of the |
|
|
|
* <p>The {@link MockitoSession#setStrictness(Strictness) strictness} of the |
|
|
|
* session defaults to {@link Strictness#STRICT_STUBS}. Use |
|
|
|
* session defaults to {@link Strictness#STRICT_STUBS}. Use |
|
|
|
* {@link MockitoBeanSettings} to specify a different strictness. |
|
|
|
* {@link MockitoBeanSettings @MockitoBeanSettings} to specify a different strictness. |
|
|
|
* |
|
|
|
* |
|
|
|
* <p>The automatic reset support for {@code @MockBean} and {@code @SpyBean} is |
|
|
|
* <p>The automatic reset support for {@code @MockBean} and {@code @SpyBean} is |
|
|
|
* handled by the {@link MockitoResetTestExecutionListener}. |
|
|
|
* handled by the {@link MockitoResetTestExecutionListener}. |
|
|
|
@ -50,8 +51,11 @@ import org.springframework.util.ReflectionUtils.FieldCallback; |
|
|
|
* @author Phillip Webb |
|
|
|
* @author Phillip Webb |
|
|
|
* @author Andy Wilkinson |
|
|
|
* @author Andy Wilkinson |
|
|
|
* @author Moritz Halbritter |
|
|
|
* @author Moritz Halbritter |
|
|
|
|
|
|
|
* @author Sam Brannen |
|
|
|
* @since 6.2 |
|
|
|
* @since 6.2 |
|
|
|
* @see MockitoResetTestExecutionListener |
|
|
|
* @see MockitoResetTestExecutionListener |
|
|
|
|
|
|
|
* @see MockitoBean @MockitoBean |
|
|
|
|
|
|
|
* @see MockitoSpyBean @MockitoSpyBean |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public class MockitoTestExecutionListener extends AbstractTestExecutionListener { |
|
|
|
public class MockitoTestExecutionListener extends AbstractTestExecutionListener { |
|
|
|
|
|
|
|
|
|
|
|
@ -101,7 +105,7 @@ public class MockitoTestExecutionListener extends AbstractTestExecutionListener |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private void initMocks(TestContext testContext) { |
|
|
|
private void initMocks(TestContext testContext) { |
|
|
|
if (hasMockitoAnnotations(testContext)) { |
|
|
|
if (MockitoAnnotationDetector.hasMockitoAnnotations(testContext.getTestClass())) { |
|
|
|
Object testInstance = testContext.getTestInstance(); |
|
|
|
Object testInstance = testContext.getTestInstance(); |
|
|
|
MockitoBeanSettings annotation = AnnotationUtils.findAnnotation(testInstance.getClass(), |
|
|
|
MockitoBeanSettings annotation = AnnotationUtils.findAnnotation(testInstance.getClass(), |
|
|
|
MockitoBeanSettings.class); |
|
|
|
MockitoBeanSettings.class); |
|
|
|
@ -124,51 +128,35 @@ public class MockitoTestExecutionListener extends AbstractTestExecutionListener |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private boolean hasMockitoAnnotations(TestContext testContext) { |
|
|
|
|
|
|
|
MockitoAnnotationCollector collector = new MockitoAnnotationCollector(); |
|
|
|
|
|
|
|
collector.collect(testContext.getTestClass()); |
|
|
|
|
|
|
|
return collector.hasAnnotations(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Utility class that collects {@code org.mockito} annotations and the |
|
|
|
* Utility class that detects {@code org.mockito} annotations as well as the |
|
|
|
* annotations in this package (like {@link MockitoBeanSettings}). |
|
|
|
* annotations in this package (like {@link MockitoBeanSettings @MockitoBeanSettings}). |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
private static final class MockitoAnnotationCollector implements FieldCallback { |
|
|
|
private static class MockitoAnnotationDetector { |
|
|
|
|
|
|
|
|
|
|
|
private static final String MOCKITO_BEAN_PACKAGE = MockitoBean.class.getPackageName(); |
|
|
|
private static final String MOCKITO_BEAN_PACKAGE = MockitoBeanSettings.class.getPackageName(); |
|
|
|
|
|
|
|
|
|
|
|
private static final String ORG_MOCKITO_PACKAGE = "org.mockito"; |
|
|
|
private static final String ORG_MOCKITO_PACKAGE = "org.mockito"; |
|
|
|
|
|
|
|
|
|
|
|
private final Set<Annotation> annotations = new LinkedHashSet<>(); |
|
|
|
private static final Predicate<Annotation> isMockitoAnnotation = annotation -> { |
|
|
|
|
|
|
|
String packageName = annotation.annotationType().getPackageName(); |
|
|
|
public void collect(Class<?> clazz) { |
|
|
|
return (packageName.startsWith(MOCKITO_BEAN_PACKAGE) || |
|
|
|
ReflectionUtils.doWithFields(clazz, this); |
|
|
|
packageName.startsWith(ORG_MOCKITO_PACKAGE)); |
|
|
|
for (Annotation annotation : clazz.getAnnotations()) { |
|
|
|
}; |
|
|
|
collect(annotation); |
|
|
|
|
|
|
|
} |
|
|
|
static boolean hasMockitoAnnotations(Class<?> testClass) { |
|
|
|
} |
|
|
|
Set<Annotation> annotations = new HashSet<>(); |
|
|
|
|
|
|
|
collect(testClass, annotations); |
|
|
|
@Override |
|
|
|
ReflectionUtils.doWithFields(testClass, field -> collect(field, annotations)); |
|
|
|
public void doWith(Field field) throws IllegalArgumentException { |
|
|
|
return !annotations.isEmpty(); |
|
|
|
for (Annotation annotation : field.getAnnotations()) { |
|
|
|
|
|
|
|
collect(annotation); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void collect(Annotation annotation) { |
|
|
|
|
|
|
|
String packageName = annotation.annotationType().getPackageName(); |
|
|
|
|
|
|
|
if (packageName.startsWith(MOCKITO_BEAN_PACKAGE) || |
|
|
|
|
|
|
|
packageName.startsWith(ORG_MOCKITO_PACKAGE)) { |
|
|
|
|
|
|
|
this.annotations.add(annotation); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
boolean hasAnnotations() { |
|
|
|
static void collect(AnnotatedElement annotatedElement, Set<Annotation> annotations) { |
|
|
|
return !this.annotations.isEmpty(); |
|
|
|
Arrays.stream(annotatedElement.getAnnotations()) |
|
|
|
|
|
|
|
.filter(isMockitoAnnotation) |
|
|
|
|
|
|
|
.forEach(annotations::add); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|