Add Support for Mockito spies
Add a @SpyBean annotation that can be used to create spies. Fixes gh-5538
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright 2012-2016 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
|
||||
*
|
||||
* http://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.boot.test.mock.mockito;
|
||||
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Base class for {@link MockDefinition} and {@link SpyDefinition}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @see DefinitionsParser
|
||||
*/
|
||||
abstract class Definition {
|
||||
|
||||
private static final int MULTIPLIER = 31;
|
||||
|
||||
private final String name;
|
||||
|
||||
private final MockReset reset;
|
||||
|
||||
Definition(String name, MockReset reset) {
|
||||
this.name = name;
|
||||
this.reset = (reset != null ? reset : MockReset.AFTER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name for bean.
|
||||
* @return the name or {@code null}
|
||||
*/
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the mock reset mode.
|
||||
* @return the reset mode
|
||||
*/
|
||||
public MockReset getReset() {
|
||||
return this.reset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = 1;
|
||||
result = MULTIPLIER * result + ObjectUtils.nullSafeHashCode(this.name);
|
||||
result = MULTIPLIER * result + ObjectUtils.nullSafeHashCode(this.reset);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null || !getClass().isAssignableFrom(obj.getClass())) {
|
||||
return false;
|
||||
}
|
||||
Definition other = (Definition) obj;
|
||||
boolean result = true;
|
||||
result &= ObjectUtils.nullSafeEquals(this.name, other.name);
|
||||
result &= ObjectUtils.nullSafeEquals(this.reset, other.reset);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -33,24 +33,25 @@ import org.springframework.util.ReflectionUtils.FieldCallback;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Parser to create {@link MockDefinition} from {@link MockBean @MockBean} annotations
|
||||
* declared on or in a class.
|
||||
* Parser to create {@link MockDefinition} and {@link SpyDefinition} instances from
|
||||
* {@link MockBean @MockBean} and {@link SpyBean @SpyBean} annotations declared on or in a
|
||||
* class.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class MockDefinitionsParser {
|
||||
class DefinitionsParser {
|
||||
|
||||
private final Set<MockDefinition> definitions;
|
||||
private final Set<Definition> definitions;
|
||||
|
||||
private final Map<MockDefinition, Field> fields;
|
||||
private final Map<Definition, Field> definitionFields;
|
||||
|
||||
MockDefinitionsParser() {
|
||||
this(Collections.<MockDefinition>emptySet());
|
||||
DefinitionsParser() {
|
||||
this(Collections.<Definition>emptySet());
|
||||
}
|
||||
|
||||
MockDefinitionsParser(Collection<? extends MockDefinition> existing) {
|
||||
this.definitions = new LinkedHashSet<MockDefinition>();
|
||||
this.fields = new LinkedHashMap<MockDefinition, Field>();
|
||||
DefinitionsParser(Collection<? extends Definition> existing) {
|
||||
this.definitions = new LinkedHashSet<Definition>();
|
||||
this.definitionFields = new LinkedHashMap<Definition, Field>();
|
||||
if (existing != null) {
|
||||
this.definitions.addAll(existing);
|
||||
}
|
||||
@@ -72,12 +73,16 @@ class MockDefinitionsParser {
|
||||
private void parseElement(AnnotatedElement element) {
|
||||
for (MockBean annotation : AnnotationUtils.getRepeatableAnnotations(element,
|
||||
MockBean.class, MockBeans.class)) {
|
||||
parseAnnotation(annotation, element);
|
||||
parseMockBeanAnnotation(annotation, element);
|
||||
}
|
||||
for (SpyBean annotation : AnnotationUtils.getRepeatableAnnotations(element,
|
||||
SpyBean.class, SpyBeans.class)) {
|
||||
parseSpyBeanAnnotation(annotation, element);
|
||||
}
|
||||
}
|
||||
|
||||
private void parseAnnotation(MockBean annotation, AnnotatedElement element) {
|
||||
Set<Class<?>> classesToMock = getOrDeduceClassesToMock(annotation, element);
|
||||
private void parseMockBeanAnnotation(MockBean annotation, AnnotatedElement element) {
|
||||
Set<Class<?>> classesToMock = getOrDeduceClasses(element, annotation.value());
|
||||
Assert.state(!classesToMock.isEmpty(),
|
||||
"Unable to deduce class to mock from " + element);
|
||||
if (StringUtils.hasLength(annotation.name())) {
|
||||
@@ -88,30 +93,50 @@ class MockDefinitionsParser {
|
||||
MockDefinition definition = new MockDefinition(annotation.name(), classToMock,
|
||||
annotation.extraInterfaces(), annotation.answer(),
|
||||
annotation.serializable(), annotation.reset());
|
||||
boolean isNewDefinition = this.definitions.add(definition);
|
||||
Assert.state(isNewDefinition, "Duplicate mock definition " + definition);
|
||||
if (element instanceof Field) {
|
||||
this.fields.put(definition, (Field) element);
|
||||
}
|
||||
addDefinition(element, definition, "mock");
|
||||
}
|
||||
}
|
||||
|
||||
private Set<Class<?>> getOrDeduceClassesToMock(MockBean annotation,
|
||||
AnnotatedElement element) {
|
||||
private void parseSpyBeanAnnotation(SpyBean annotation, AnnotatedElement element) {
|
||||
Set<Class<?>> classesToSpy = getOrDeduceClasses(element, annotation.value());
|
||||
Assert.state(!classesToSpy.isEmpty(),
|
||||
"Unable to deduce class to spy from " + element);
|
||||
if (StringUtils.hasLength(annotation.name())) {
|
||||
Assert.state(classesToSpy.size() == 1,
|
||||
"The name attribute can only be used when spying a single class");
|
||||
}
|
||||
for (Class<?> classToSpy : classesToSpy) {
|
||||
SpyDefinition definition = new SpyDefinition(annotation.name(), classToSpy,
|
||||
annotation.reset());
|
||||
addDefinition(element, definition, "spy");
|
||||
}
|
||||
}
|
||||
|
||||
private void addDefinition(AnnotatedElement element, Definition definition,
|
||||
String type) {
|
||||
boolean isNewDefinition = this.definitions.add(definition);
|
||||
Assert.state(isNewDefinition, "Duplicate " + type + " definition " + definition);
|
||||
if (element instanceof Field) {
|
||||
Field field = (Field) element;
|
||||
this.definitionFields.put(definition, field);
|
||||
}
|
||||
}
|
||||
|
||||
private Set<Class<?>> getOrDeduceClasses(AnnotatedElement element, Class<?>[] value) {
|
||||
Set<Class<?>> classes = new LinkedHashSet<Class<?>>();
|
||||
classes.addAll(Arrays.asList(annotation.value()));
|
||||
classes.addAll(Arrays.asList(value));
|
||||
if (classes.isEmpty() && element instanceof Field) {
|
||||
classes.add(((Field) element).getType());
|
||||
}
|
||||
return classes;
|
||||
}
|
||||
|
||||
public Set<MockDefinition> getDefinitions() {
|
||||
public Set<Definition> getDefinitions() {
|
||||
return Collections.unmodifiableSet(this.definitions);
|
||||
}
|
||||
|
||||
public Field getField(MockDefinition definition) {
|
||||
return this.fields.get(definition);
|
||||
public Field getField(Definition definition) {
|
||||
return this.definitionFields.get(definition);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -82,9 +82,9 @@ import org.springframework.test.context.junit4.SpringRunner;
|
||||
public @interface MockBean {
|
||||
|
||||
/**
|
||||
* The name of the bean that should be registered with the application context. If not
|
||||
* specified the name will either be generated or, if the mock replaces an existing
|
||||
* bean, the existing name will be used.
|
||||
* The name of the bean to register or replace. If not specified the name will either
|
||||
* be generated or, if the mock replaces an existing bean, the existing name will be
|
||||
* used.
|
||||
* @return the name of the bean
|
||||
*/
|
||||
String name() default "";
|
||||
|
||||
@@ -35,12 +35,10 @@ import org.springframework.util.StringUtils;
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class MockDefinition {
|
||||
class MockDefinition extends Definition {
|
||||
|
||||
private static final int MULTIPLIER = 31;
|
||||
|
||||
private final String name;
|
||||
|
||||
private final Class<?> classToMock;
|
||||
|
||||
private final Set<Class<?>> extraInterfaces;
|
||||
@@ -49,21 +47,18 @@ class MockDefinition {
|
||||
|
||||
private final boolean serializable;
|
||||
|
||||
private final MockReset reset;
|
||||
|
||||
MockDefinition(Class<?> classToMock) {
|
||||
this(null, classToMock, null, null, false, null);
|
||||
}
|
||||
|
||||
MockDefinition(String name, Class<?> classToMock, Class<?>[] extraInterfaces,
|
||||
Answers answer, boolean serializable, MockReset reset) {
|
||||
super(name, reset);
|
||||
Assert.notNull(classToMock, "ClassToMock must not be null");
|
||||
this.name = name;
|
||||
this.classToMock = classToMock;
|
||||
this.extraInterfaces = asClassSet(extraInterfaces);
|
||||
this.answer = (answer != null ? answer : Answers.RETURNS_DEFAULTS);
|
||||
this.serializable = serializable;
|
||||
this.reset = (reset != null ? reset : MockReset.AFTER);
|
||||
}
|
||||
|
||||
private Set<Class<?>> asClassSet(Class<?>[] classes) {
|
||||
@@ -74,14 +69,6 @@ class MockDefinition {
|
||||
return Collections.unmodifiableSet(classSet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name for bean.
|
||||
* @return the name or {@code null}
|
||||
*/
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the classes that should be mocked.
|
||||
* @return the class to mock; never {@code null}
|
||||
@@ -114,23 +101,13 @@ class MockDefinition {
|
||||
return this.serializable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the mock reset mode.
|
||||
* @return the reset mode
|
||||
*/
|
||||
public MockReset getReset() {
|
||||
return this.reset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = 1;
|
||||
result = MULTIPLIER * result + ObjectUtils.nullSafeHashCode(this.name);
|
||||
int result = super.hashCode();
|
||||
result = MULTIPLIER * result + ObjectUtils.nullSafeHashCode(this.classToMock);
|
||||
result = MULTIPLIER * result + ObjectUtils.nullSafeHashCode(this.extraInterfaces);
|
||||
result = MULTIPLIER * result + ObjectUtils.nullSafeHashCode(this.answer);
|
||||
result = MULTIPLIER * result + (this.serializable ? 1231 : 1237);
|
||||
result = MULTIPLIER * result + ObjectUtils.nullSafeHashCode(this.reset);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -143,32 +120,30 @@ class MockDefinition {
|
||||
return false;
|
||||
}
|
||||
MockDefinition other = (MockDefinition) obj;
|
||||
boolean result = true;
|
||||
result &= ObjectUtils.nullSafeEquals(this.name, other.name);
|
||||
boolean result = super.equals(obj);
|
||||
result &= ObjectUtils.nullSafeEquals(this.classToMock, other.classToMock);
|
||||
result &= ObjectUtils.nullSafeEquals(this.extraInterfaces, other.extraInterfaces);
|
||||
result &= ObjectUtils.nullSafeEquals(this.answer, other.answer);
|
||||
result &= this.serializable == other.serializable;
|
||||
result &= ObjectUtils.nullSafeEquals(this.reset, other.reset);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringCreator(this).append("name", this.name)
|
||||
return new ToStringCreator(this).append("name", getName())
|
||||
.append("classToMock", this.classToMock)
|
||||
.append("extraInterfaces", this.extraInterfaces)
|
||||
.append("answer", this.answer).append("serializable", this.serializable)
|
||||
.append("reset", this.reset).toString();
|
||||
.append("reset", getReset()).toString();
|
||||
}
|
||||
|
||||
public <T> T createMock() {
|
||||
return createMock(this.name);
|
||||
return createMock(getName());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T createMock(String name) {
|
||||
MockSettings settings = MockReset.withSettings(this.reset);
|
||||
MockSettings settings = MockReset.withSettings(getReset());
|
||||
if (StringUtils.hasLength(name)) {
|
||||
settings.name(name);
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.boot.test.mock.mockito;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
@@ -30,10 +31,10 @@ import org.springframework.test.context.MergedContextConfiguration;
|
||||
*/
|
||||
class MockitoContextCustomizer implements ContextCustomizer {
|
||||
|
||||
private final Set<MockDefinition> definitions;
|
||||
private final Set<Definition> definitions;
|
||||
|
||||
MockitoContextCustomizer(Set<MockDefinition> definitions) {
|
||||
this.definitions = definitions;
|
||||
MockitoContextCustomizer(Set<? extends Definition> definitions) {
|
||||
this.definitions = new LinkedHashSet<Definition>(definitions);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -34,7 +34,7 @@ class MockitoContextCustomizerFactory implements ContextCustomizerFactory {
|
||||
List<ContextConfigurationAttributes> configAttributes) {
|
||||
// We gather the explicit mock definitions here since they form part of the
|
||||
// MergedContextConfiguration key. Different mocks need to have a different key
|
||||
MockDefinitionsParser parser = new MockDefinitionsParser();
|
||||
DefinitionsParser parser = new DefinitionsParser();
|
||||
parser.parse(testClass);
|
||||
return new MockitoContextCustomizer(parser.getDefinitions());
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.config.ConstructorArgumentValues;
|
||||
import org.springframework.beans.factory.config.ConstructorArgumentValues.ValueHolder;
|
||||
@@ -66,7 +67,7 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
public class MockitoPostProcessor extends InstantiationAwareBeanPostProcessorAdapter
|
||||
implements BeanClassLoaderAware, BeanFactoryAware, BeanFactoryPostProcessor,
|
||||
Ordered {
|
||||
BeanPostProcessor, Ordered {
|
||||
|
||||
private static final String BEAN_NAME = MockitoPostProcessor.class.getName();
|
||||
|
||||
@@ -74,7 +75,7 @@ public class MockitoPostProcessor extends InstantiationAwareBeanPostProcessorAda
|
||||
.getQualifiedAttributeName(ConfigurationClassPostProcessor.class,
|
||||
"configurationClass");
|
||||
|
||||
private final Set<MockDefinition> mockDefinitions;
|
||||
private final Set<Definition> definitions;
|
||||
|
||||
private ClassLoader classLoader;
|
||||
|
||||
@@ -82,17 +83,19 @@ public class MockitoPostProcessor extends InstantiationAwareBeanPostProcessorAda
|
||||
|
||||
private final BeanNameGenerator beanNameGenerator = new DefaultBeanNameGenerator();
|
||||
|
||||
private Map<MockDefinition, String> beanNameRegistry = new HashMap<MockDefinition, String>();
|
||||
private Map<Definition, String> beanNameRegistry = new HashMap<Definition, String>();
|
||||
|
||||
private Map<Field, String> fieldRegistry = new HashMap<Field, String>();
|
||||
|
||||
private Map<String, SpyDefinition> spies = new HashMap<String, SpyDefinition>();
|
||||
|
||||
/**
|
||||
* Create a new {@link MockitoPostProcessor} instance with the given initial
|
||||
* definitions.
|
||||
* @param mockDefinitions the initial definitions
|
||||
* @param definitions the initial definitions
|
||||
*/
|
||||
public MockitoPostProcessor(Set<MockDefinition> mockDefinitions) {
|
||||
this.mockDefinitions = mockDefinitions;
|
||||
public MockitoPostProcessor(Set<Definition> definitions) {
|
||||
this.definitions = definitions;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -118,14 +121,14 @@ public class MockitoPostProcessor extends InstantiationAwareBeanPostProcessorAda
|
||||
|
||||
private void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory,
|
||||
BeanDefinitionRegistry registry) {
|
||||
MockDefinitionsParser parser = new MockDefinitionsParser(this.mockDefinitions);
|
||||
DefinitionsParser parser = new DefinitionsParser(this.definitions);
|
||||
for (Class<?> configurationClass : getConfigurationClasses(beanFactory)) {
|
||||
parser.parse(configurationClass);
|
||||
}
|
||||
Set<MockDefinition> definitions = parser.getDefinitions();
|
||||
for (MockDefinition definition : definitions) {
|
||||
Set<Definition> definitions = parser.getDefinitions();
|
||||
for (Definition definition : definitions) {
|
||||
Field field = parser.getField(definition);
|
||||
registerMock(beanFactory, registry, definition, field);
|
||||
register(beanFactory, registry, definition, field);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,20 +155,23 @@ public class MockitoPostProcessor extends InstantiationAwareBeanPostProcessorAda
|
||||
return definitions;
|
||||
}
|
||||
|
||||
void inject(Field field, Object target, MockDefinition definition) {
|
||||
String beanName = this.beanNameRegistry.get(definition);
|
||||
Assert.state(StringUtils.hasLength(beanName),
|
||||
"No mock found for definition " + definition);
|
||||
injectMock(field, target, beanName);
|
||||
private void register(ConfigurableListableBeanFactory beanFactory,
|
||||
BeanDefinitionRegistry registry, Definition definition, Field field) {
|
||||
if (definition instanceof MockDefinition) {
|
||||
registerMock(beanFactory, registry, (MockDefinition) definition, field);
|
||||
}
|
||||
else if (definition instanceof SpyDefinition) {
|
||||
registerSpy(beanFactory, registry, (SpyDefinition) definition, field);
|
||||
}
|
||||
}
|
||||
|
||||
private void registerMock(ConfigurableListableBeanFactory beanFactory,
|
||||
BeanDefinitionRegistry registry, MockDefinition mockDefinition, Field field) {
|
||||
RootBeanDefinition beanDefinition = createBeanDefinition(mockDefinition);
|
||||
String name = getBeanName(beanFactory, registry, mockDefinition, beanDefinition);
|
||||
BeanDefinitionRegistry registry, MockDefinition definition, Field field) {
|
||||
RootBeanDefinition beanDefinition = createBeanDefinition(definition);
|
||||
String name = getBeanName(beanFactory, registry, definition, beanDefinition);
|
||||
beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(1, name);
|
||||
registry.registerBeanDefinition(name, beanDefinition);
|
||||
this.beanNameRegistry.put(mockDefinition, name);
|
||||
this.beanNameRegistry.put(definition, name);
|
||||
if (field != null) {
|
||||
this.fieldRegistry.put(field, name);
|
||||
}
|
||||
@@ -184,12 +190,12 @@ public class MockitoPostProcessor extends InstantiationAwareBeanPostProcessorAda
|
||||
|
||||
/**
|
||||
* Factory method used by defined beans to actually create the mock.
|
||||
* @param definition the mock definition
|
||||
* @param mockDefinition the mock definition
|
||||
* @param name the bean name
|
||||
* @return the mock instance
|
||||
*/
|
||||
protected final Object createMock(MockDefinition definition, String name) {
|
||||
return definition.createMock(name + " bean");
|
||||
protected final Object createMock(MockDefinition mockDefinition, String name) {
|
||||
return mockDefinition.createMock(name + " bean");
|
||||
}
|
||||
|
||||
private String getBeanName(ConfigurableListableBeanFactory beanFactory,
|
||||
@@ -212,6 +218,60 @@ public class MockitoPostProcessor extends InstantiationAwareBeanPostProcessorAda
|
||||
+ new TreeSet<String>(Arrays.asList(existingBeans)));
|
||||
}
|
||||
|
||||
private void registerSpy(ConfigurableListableBeanFactory beanFactory,
|
||||
BeanDefinitionRegistry registry, SpyDefinition spyDefinition, Field field) {
|
||||
String[] existingBeans = beanFactory
|
||||
.getBeanNamesForType(spyDefinition.getClassToSpy());
|
||||
if (ObjectUtils.isEmpty(existingBeans)) {
|
||||
createSpy(registry, spyDefinition, field);
|
||||
}
|
||||
else {
|
||||
registerSpies(spyDefinition, field, existingBeans);
|
||||
}
|
||||
}
|
||||
|
||||
private void createSpy(BeanDefinitionRegistry registry, SpyDefinition spyDefinition,
|
||||
Field field) {
|
||||
RootBeanDefinition beanDefinition = new RootBeanDefinition(
|
||||
spyDefinition.getClassToSpy());
|
||||
String beanName = this.beanNameGenerator.generateBeanName(beanDefinition,
|
||||
registry);
|
||||
registry.registerBeanDefinition(beanName, beanDefinition);
|
||||
registerSpy(spyDefinition, field, beanName);
|
||||
}
|
||||
|
||||
private void registerSpies(SpyDefinition spyDefinition, Field field,
|
||||
String[] existingBeans) {
|
||||
if (field != null) {
|
||||
Assert.state(field == null || existingBeans.length == 1,
|
||||
"Unable to register spy bean "
|
||||
+ spyDefinition.getClassToSpy().getName()
|
||||
+ " expected a single existing bean to replace but found "
|
||||
+ new TreeSet<String>(Arrays.asList(existingBeans)));
|
||||
}
|
||||
for (String beanName : existingBeans) {
|
||||
registerSpy(spyDefinition, field, beanName);
|
||||
}
|
||||
}
|
||||
|
||||
private void registerSpy(SpyDefinition spyDefinition, Field field, String beanName) {
|
||||
this.spies.put(beanName, spyDefinition);
|
||||
this.beanNameRegistry.put(spyDefinition, beanName);
|
||||
if (field != null) {
|
||||
this.fieldRegistry.put(field, beanName);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName)
|
||||
throws BeansException {
|
||||
SpyDefinition spyDefinition = this.spies.get(beanName);
|
||||
if (spyDefinition != null) {
|
||||
bean = spyDefinition.createSpy(beanName, bean);
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PropertyValues postProcessPropertyValues(PropertyValues pvs,
|
||||
PropertyDescriptor[] pds, final Object bean, String beanName)
|
||||
@@ -231,18 +291,27 @@ public class MockitoPostProcessor extends InstantiationAwareBeanPostProcessorAda
|
||||
private void postProcessField(Object bean, Field field) {
|
||||
String beanName = this.fieldRegistry.get(field);
|
||||
if (StringUtils.hasLength(beanName)) {
|
||||
injectMock(field, bean, beanName);
|
||||
inject(field, bean, beanName);
|
||||
}
|
||||
}
|
||||
|
||||
private void injectMock(Field field, Object target, String beanName) {
|
||||
void inject(Field field, Object target, Definition definition) {
|
||||
String beanName = this.beanNameRegistry.get(definition);
|
||||
Assert.state(StringUtils.hasLength(beanName),
|
||||
"No bean found for definition " + definition);
|
||||
inject(field, target, beanName);
|
||||
}
|
||||
|
||||
private void inject(Field field, Object target, String beanName) {
|
||||
try {
|
||||
field.setAccessible(true);
|
||||
Object mockBean = this.beanFactory.getBean(beanName, field.getType());
|
||||
ReflectionUtils.setField(field, target, mockBean);
|
||||
Assert.state(ReflectionUtils.getField(field, target) == null,
|
||||
"The field " + field + " cannot have an existing value");
|
||||
Object bean = this.beanFactory.getBean(beanName, field.getType());
|
||||
ReflectionUtils.setField(field, target, bean);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
throw new BeanCreationException("Could not inject mock field: " + field, ex);
|
||||
throw new BeanCreationException("Could not inject field: " + field, ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -264,11 +333,11 @@ public class MockitoPostProcessor extends InstantiationAwareBeanPostProcessorAda
|
||||
* Register the processor with a {@link BeanDefinitionRegistry}. Not required when
|
||||
* using the {@link SpringRunner} as registration is automatic.
|
||||
* @param registry the bean definition registry
|
||||
* @param mockDefinitions the initial mock definitions
|
||||
* @param definitions the initial mock/spy definitions
|
||||
*/
|
||||
public static void register(BeanDefinitionRegistry registry,
|
||||
Set<MockDefinition> mockDefinitions) {
|
||||
register(registry, MockitoPostProcessor.class, mockDefinitions);
|
||||
Set<Definition> definitions) {
|
||||
register(registry, MockitoPostProcessor.class, definitions);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -276,18 +345,18 @@ public class MockitoPostProcessor extends InstantiationAwareBeanPostProcessorAda
|
||||
* using the {@link SpringRunner} as registration is automatic.
|
||||
* @param registry the bean definition registry
|
||||
* @param postProcessor the post processor class to register
|
||||
* @param mockDefinitions the initial mock definitions
|
||||
* @param definitions the initial mock/spy definitions
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static void register(BeanDefinitionRegistry registry,
|
||||
Class<? extends MockitoPostProcessor> postProcessor,
|
||||
Set<MockDefinition> mockDefinitions) {
|
||||
Set<Definition> definitions) {
|
||||
BeanDefinition definition = getOrAddBeanDefinition(registry, postProcessor);
|
||||
ValueHolder constructorArg = definition.getConstructorArgumentValues()
|
||||
.getIndexedArgumentValue(0, Set.class);
|
||||
Set<MockDefinition> existing = (Set<MockDefinition>) constructorArg.getValue();
|
||||
if (mockDefinitions != null) {
|
||||
existing.addAll(mockDefinitions);
|
||||
Set<Definition> existing = (Set<Definition>) constructorArg.getValue();
|
||||
if (definitions != null) {
|
||||
existing.addAll(definitions);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -38,10 +38,11 @@ import org.springframework.util.ReflectionUtils.FieldCallback;
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class MockitoInitializeTestExecutionListener extends AbstractTestExecutionListener {
|
||||
class MockitoTestExecutionListener extends AbstractTestExecutionListener {
|
||||
|
||||
@Override
|
||||
public void prepareTestInstance(TestContext testContext) throws Exception {
|
||||
System.out.println("Prepare");
|
||||
if (hasMockitoAnnotations(testContext)) {
|
||||
MockitoAnnotations.initMocks(testContext.getTestInstance());
|
||||
}
|
||||
@@ -55,18 +56,18 @@ class MockitoInitializeTestExecutionListener extends AbstractTestExecutionListen
|
||||
}
|
||||
|
||||
private void injectFields(TestContext testContext) {
|
||||
MockDefinitionsParser parser = new MockDefinitionsParser();
|
||||
DefinitionsParser parser = new DefinitionsParser();
|
||||
parser.parse(testContext.getTestClass());
|
||||
if (!parser.getDefinitions().isEmpty()) {
|
||||
injectFields(testContext, parser);
|
||||
}
|
||||
}
|
||||
|
||||
private void injectFields(TestContext testContext, MockDefinitionsParser parser) {
|
||||
private void injectFields(TestContext testContext, DefinitionsParser parser) {
|
||||
ApplicationContext applicationContext = testContext.getApplicationContext();
|
||||
MockitoPostProcessor postProcessor = applicationContext
|
||||
.getBean(MockitoPostProcessor.class);
|
||||
for (MockDefinition definition : parser.getDefinitions()) {
|
||||
for (Definition definition : parser.getDefinitions()) {
|
||||
Field field = parser.getField(definition);
|
||||
if (field != null) {
|
||||
postProcessor.inject(field, testContext.getTestInstance(), definition);
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright 2012-2016 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
|
||||
*
|
||||
* http://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.boot.test.mock.mockito;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Repeatable;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
/**
|
||||
* Annotation that can be used to appy Mockto spies to a Spring
|
||||
* {@link ApplicationContext}. Can be used as a class level annotation or on fields in
|
||||
* either {@code @Configuration} classes, or test classes that are
|
||||
* {@link RunWith @RunWith} the {@link SpringRunner}.
|
||||
* <p>
|
||||
* Spies can be applied by type or by {@link #name() bean name}. All beans in the context
|
||||
* of the same type will be wrapped with the spy, if no existing bean is defined a new one
|
||||
* will be added.
|
||||
* <p>
|
||||
* When {@code @SpyBean} is used on a field, as well as being registered in the
|
||||
* application context, the spy will also be injected into the field. Typical usage might
|
||||
* be: <pre class="code">
|
||||
* @RunWith(SpringRunner.class)
|
||||
* public class ExampleTests {
|
||||
*
|
||||
* @SpyBean
|
||||
* private ExampleService service;
|
||||
*
|
||||
* @Autowired
|
||||
* private UserOfService userOfService;
|
||||
*
|
||||
* @Test
|
||||
* public void testUserOfService() {
|
||||
* String actual = this.userOfService.makeUse();
|
||||
* assertEquals("Was: Hello", actual);
|
||||
* verify(this.service).greet();
|
||||
* }
|
||||
*
|
||||
* @Configuration
|
||||
* @Import(UserOfService.class) // A @Component injected with ExampleService
|
||||
* static class Config {
|
||||
* }
|
||||
*
|
||||
*
|
||||
* }
|
||||
* </pre>
|
||||
* <p>
|
||||
* This annotation is {@code @Repeatable} and may be specified multiple times when working
|
||||
* with Java 8 or contained within an {@link SpyBeans @SpyBeans} annotation.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @since 1.4.0
|
||||
* @see MockitoPostProcessor
|
||||
*/
|
||||
@Target({ ElementType.TYPE, ElementType.FIELD })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Repeatable(SpyBeans.class)
|
||||
public @interface SpyBean {
|
||||
|
||||
/**
|
||||
* The name of the bean to spy. If not specified the name will either be generated or,
|
||||
* if the spy is for an existing bean, the existing name will be used.
|
||||
* @return the name of the bean
|
||||
*/
|
||||
String name() default "";
|
||||
|
||||
/**
|
||||
* The classes to spy. This is an alias of {@link #classes()} which can be used for
|
||||
* brevity if no other attributes are defined. See {@link #classes()} for details.
|
||||
* @return the classes to mock
|
||||
*/
|
||||
@AliasFor("classes")
|
||||
Class<?>[] value() default {};
|
||||
|
||||
/**
|
||||
* The classes to spy. Each class specified here will result in a spy being applied.
|
||||
* Classes can be omitted when the annotation is used on a field.
|
||||
* <p>
|
||||
* When {@code @MockBean} also defines a {@code name} this attribute can only contain
|
||||
* a single value.
|
||||
* <p>
|
||||
* If this is the only attribute specified consider using the {@code value} alias
|
||||
* instead.
|
||||
* @return the classes to mock
|
||||
*/
|
||||
@AliasFor("value")
|
||||
Class<?>[] classes() default {};
|
||||
|
||||
/**
|
||||
* The reset mode to apply to the spied bean. The default is {@link MockReset#AFTER}
|
||||
* meaning that spies are automatically reset after each test method is invoked.
|
||||
* @return the reset mode
|
||||
*/
|
||||
MockReset reset() default MockReset.AFTER;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2012-2016 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
|
||||
*
|
||||
* http://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.boot.test.mock.mockito;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Container annotation that aggregates several {@link SpyBean} annotations.
|
||||
* <p>
|
||||
* Can be used natively, declaring several nested {@link SpyBean} annotations. Can also be
|
||||
* used in conjunction with Java 8's support for <em>repeatable annotations</em>, where
|
||||
* {@link SpyBean} can simply be declared several times on the same
|
||||
* {@linkplain ElementType#TYPE type}, implicitly generating this container annotation.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @since 1.4.0
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
@Documented
|
||||
public @interface SpyBeans {
|
||||
|
||||
/**
|
||||
* Return the contained {@link SpyBean} annotations.
|
||||
* @return the spy beans
|
||||
*/
|
||||
SpyBean[] value();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright 2012-2016 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
|
||||
*
|
||||
* http://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.boot.test.mock.mockito;
|
||||
|
||||
import org.mockito.MockSettings;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.internal.util.MockUtil;
|
||||
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* A complete definition that can be used to create a Mockito spy.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class SpyDefinition extends Definition {
|
||||
|
||||
private MockUtil mockUtil = new MockUtil();
|
||||
|
||||
private static final int MULTIPLIER = 31;
|
||||
|
||||
private final Class<?> classToSpy;
|
||||
|
||||
SpyDefinition(String name, Class<?> classToSpy, MockReset reset) {
|
||||
super(name, reset);
|
||||
Assert.notNull(classToSpy, "ClassToSpy must not be null");
|
||||
this.classToSpy = classToSpy;
|
||||
|
||||
}
|
||||
|
||||
public Class<?> getClassToSpy() {
|
||||
return this.classToSpy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = super.hashCode();
|
||||
result = MULTIPLIER * result + ObjectUtils.nullSafeHashCode(this.classToSpy);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null || obj.getClass() != getClass()) {
|
||||
return false;
|
||||
}
|
||||
SpyDefinition other = (SpyDefinition) obj;
|
||||
boolean result = super.equals(obj);
|
||||
result &= ObjectUtils.nullSafeEquals(this.classToSpy, other.classToSpy);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringCreator(this).append("name", getName())
|
||||
.append("classToSpy", this.classToSpy).append("reset", getReset())
|
||||
.toString();
|
||||
}
|
||||
|
||||
public <T> T createSpy(Object instance) {
|
||||
return createSpy(getName(), instance);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T createSpy(String name, Object instance) {
|
||||
Assert.notNull(instance, "Instance must not be null");
|
||||
Assert.isInstanceOf(this.classToSpy, instance);
|
||||
if (this.mockUtil.isSpy(instance)) {
|
||||
return (T) instance;
|
||||
}
|
||||
MockSettings settings = MockReset.withSettings(getReset());
|
||||
if (StringUtils.hasLength(name)) {
|
||||
settings.name(name);
|
||||
}
|
||||
settings.spiedInstance(instance);
|
||||
settings.defaultAnswer(Mockito.CALLS_REAL_METHODS);
|
||||
return (T) Mockito.mock(instance.getClass(), settings);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,5 +7,5 @@ org.springframework.boot.test.mock.mockito.MockitoContextCustomizerFactory
|
||||
|
||||
# Test Execution Listeners
|
||||
org.springframework.test.context.TestExecutionListener=\
|
||||
org.springframework.boot.test.mock.mockito.MockitoInitializeTestExecutionListener,\
|
||||
org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener,\
|
||||
org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener
|
||||
|
||||
@@ -0,0 +1,292 @@
|
||||
/*
|
||||
* Copyright 2012-2016 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
|
||||
*
|
||||
* http://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.boot.test.mock.mockito;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.mockito.Answers;
|
||||
|
||||
import org.springframework.boot.test.mock.mockito.example.ExampleExtraInterface;
|
||||
import org.springframework.boot.test.mock.mockito.example.ExampleService;
|
||||
import org.springframework.boot.test.mock.mockito.example.ExampleServiceCaller;
|
||||
import org.springframework.boot.test.mock.mockito.example.RealExampleService;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link DefinitionsParser}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class DefinitionsParserTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
private DefinitionsParser parser = new DefinitionsParser();
|
||||
|
||||
@Test
|
||||
public void parseSingleMockBean() {
|
||||
this.parser.parse(SingleMockBean.class);
|
||||
assertThat(getDefinitions()).hasSize(1);
|
||||
assertThat(getMockDefinition(0).getClassToMock()).isEqualTo(ExampleService.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseRepeatMockBean() {
|
||||
this.parser.parse(RepeatMockBean.class);
|
||||
assertThat(getDefinitions()).hasSize(2);
|
||||
assertThat(getMockDefinition(0).getClassToMock()).isEqualTo(ExampleService.class);
|
||||
assertThat(getMockDefinition(1).getClassToMock())
|
||||
.isEqualTo(ExampleServiceCaller.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseMockBeanAttributes() throws Exception {
|
||||
this.parser.parse(MockBeanAttributes.class);
|
||||
assertThat(getDefinitions()).hasSize(1);
|
||||
MockDefinition definition = getMockDefinition(0);
|
||||
assertThat(definition.getName()).isEqualTo("Name");
|
||||
assertThat(definition.getClassToMock()).isEqualTo(ExampleService.class);
|
||||
assertThat(definition.getExtraInterfaces())
|
||||
.containsExactly(ExampleExtraInterface.class);
|
||||
assertThat(definition.getAnswer()).isEqualTo(Answers.RETURNS_SMART_NULLS);
|
||||
assertThat(definition.isSerializable()).isEqualTo(true);
|
||||
assertThat(definition.getReset()).isEqualTo(MockReset.NONE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseMockBeanOnClassAndField() throws Exception {
|
||||
this.parser.parse(MockBeanOnClassAndField.class);
|
||||
assertThat(getDefinitions()).hasSize(2);
|
||||
assertThat(getMockDefinition(0).getClassToMock()).isEqualTo(ExampleService.class);
|
||||
assertThat(getMockDefinition(1).getClassToMock())
|
||||
.isEqualTo(ExampleServiceCaller.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseMockBeanInferClassToMock() throws Exception {
|
||||
this.parser.parse(MockBeanInferClassToMock.class);
|
||||
assertThat(getDefinitions()).hasSize(1);
|
||||
assertThat(getMockDefinition(0).getClassToMock()).isEqualTo(ExampleService.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseMockBeanMissingClassToMock() throws Exception {
|
||||
this.thrown.expect(IllegalStateException.class);
|
||||
this.thrown.expectMessage("Unable to deduce class to mock");
|
||||
this.parser.parse(MockBeanMissingClassToMock.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseMockBeanMultipleClasses() throws Exception {
|
||||
this.parser.parse(MockBeanMultipleClasses.class);
|
||||
assertThat(getDefinitions()).hasSize(2);
|
||||
assertThat(getMockDefinition(0).getClassToMock()).isEqualTo(ExampleService.class);
|
||||
assertThat(getMockDefinition(1).getClassToMock())
|
||||
.isEqualTo(ExampleServiceCaller.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseMockBeanMultipleClassesWithName() throws Exception {
|
||||
this.thrown.expect(IllegalStateException.class);
|
||||
this.thrown.expectMessage(
|
||||
"The name attribute can only be used when mocking a single class");
|
||||
this.parser.parse(MockBeanMultipleClassesWithName.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseSingleSpyBean() {
|
||||
this.parser.parse(SingleSpyBean.class);
|
||||
assertThat(getDefinitions()).hasSize(1);
|
||||
assertThat(getSpyDefinition(0).getClassToSpy())
|
||||
.isEqualTo(RealExampleService.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseRepeatSpyBean() {
|
||||
this.parser.parse(RepeatSpyBean.class);
|
||||
assertThat(getDefinitions()).hasSize(2);
|
||||
assertThat(getSpyDefinition(0).getClassToSpy())
|
||||
.isEqualTo(RealExampleService.class);
|
||||
assertThat(getSpyDefinition(1).getClassToSpy())
|
||||
.isEqualTo(ExampleServiceCaller.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseSpyBeanAttributes() throws Exception {
|
||||
this.parser.parse(SpyBeanAttributes.class);
|
||||
assertThat(getDefinitions()).hasSize(1);
|
||||
SpyDefinition definition = getSpyDefinition(0);
|
||||
assertThat(definition.getName()).isEqualTo("Name");
|
||||
assertThat(definition.getClassToSpy()).isEqualTo(RealExampleService.class);
|
||||
assertThat(definition.getReset()).isEqualTo(MockReset.NONE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseSpyBeanOnClassAndField() throws Exception {
|
||||
this.parser.parse(SpyBeanOnClassAndField.class);
|
||||
assertThat(getDefinitions()).hasSize(2);
|
||||
assertThat(getSpyDefinition(0).getClassToSpy())
|
||||
.isEqualTo(RealExampleService.class);
|
||||
assertThat(getSpyDefinition(1).getClassToSpy())
|
||||
.isEqualTo(ExampleServiceCaller.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseSpyBeanInferClassToMock() throws Exception {
|
||||
this.parser.parse(SpyBeanInferClassToMock.class);
|
||||
assertThat(getDefinitions()).hasSize(1);
|
||||
assertThat(getSpyDefinition(0).getClassToSpy())
|
||||
.isEqualTo(RealExampleService.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseSpyBeanMissingClassToMock() throws Exception {
|
||||
this.thrown.expect(IllegalStateException.class);
|
||||
this.thrown.expectMessage("Unable to deduce class to spy");
|
||||
this.parser.parse(SpyBeanMissingClassToMock.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseSpyBeanMultipleClasses() throws Exception {
|
||||
this.parser.parse(SpyBeanMultipleClasses.class);
|
||||
assertThat(getDefinitions()).hasSize(2);
|
||||
assertThat(getSpyDefinition(0).getClassToSpy())
|
||||
.isEqualTo(RealExampleService.class);
|
||||
assertThat(getSpyDefinition(1).getClassToSpy())
|
||||
.isEqualTo(ExampleServiceCaller.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseSpyBeanMultipleClassesWithName() throws Exception {
|
||||
this.thrown.expect(IllegalStateException.class);
|
||||
this.thrown.expectMessage(
|
||||
"The name attribute can only be used when spying a single class");
|
||||
this.parser.parse(SpyBeanMultipleClassesWithName.class);
|
||||
}
|
||||
|
||||
private MockDefinition getMockDefinition(int index) {
|
||||
return (MockDefinition) getDefinitions().get(index);
|
||||
}
|
||||
|
||||
private SpyDefinition getSpyDefinition(int index) {
|
||||
return (SpyDefinition) getDefinitions().get(index);
|
||||
}
|
||||
|
||||
private List<Definition> getDefinitions() {
|
||||
return new ArrayList<Definition>(this.parser.getDefinitions());
|
||||
}
|
||||
|
||||
@MockBean(ExampleService.class)
|
||||
static class SingleMockBean {
|
||||
|
||||
}
|
||||
|
||||
@MockBeans({ @MockBean(ExampleService.class), @MockBean(ExampleServiceCaller.class) })
|
||||
static class RepeatMockBean {
|
||||
|
||||
}
|
||||
|
||||
@MockBean(name = "Name", classes = ExampleService.class, extraInterfaces = ExampleExtraInterface.class, answer = Answers.RETURNS_SMART_NULLS, serializable = true, reset = MockReset.NONE)
|
||||
static class MockBeanAttributes {
|
||||
|
||||
}
|
||||
|
||||
@MockBean(ExampleService.class)
|
||||
static class MockBeanOnClassAndField {
|
||||
|
||||
@MockBean(ExampleServiceCaller.class)
|
||||
private Object caller;
|
||||
|
||||
}
|
||||
|
||||
@MockBean({ ExampleService.class, ExampleServiceCaller.class })
|
||||
static class MockBeanMultipleClasses {
|
||||
|
||||
}
|
||||
|
||||
@MockBean(name = "name", classes = { ExampleService.class,
|
||||
ExampleServiceCaller.class })
|
||||
static class MockBeanMultipleClassesWithName {
|
||||
|
||||
}
|
||||
|
||||
static class MockBeanInferClassToMock {
|
||||
|
||||
@MockBean
|
||||
private ExampleService exampleService;
|
||||
|
||||
}
|
||||
|
||||
@MockBean
|
||||
static class MockBeanMissingClassToMock {
|
||||
|
||||
}
|
||||
|
||||
@SpyBean(RealExampleService.class)
|
||||
static class SingleSpyBean {
|
||||
|
||||
}
|
||||
|
||||
@SpyBeans({ @SpyBean(RealExampleService.class),
|
||||
@SpyBean(ExampleServiceCaller.class) })
|
||||
static class RepeatSpyBean {
|
||||
|
||||
}
|
||||
|
||||
@SpyBean(name = "Name", classes = RealExampleService.class, reset = MockReset.NONE)
|
||||
static class SpyBeanAttributes {
|
||||
|
||||
}
|
||||
|
||||
@SpyBean(RealExampleService.class)
|
||||
static class SpyBeanOnClassAndField {
|
||||
|
||||
@SpyBean(ExampleServiceCaller.class)
|
||||
private Object caller;
|
||||
|
||||
}
|
||||
|
||||
@SpyBean({ RealExampleService.class, ExampleServiceCaller.class })
|
||||
static class SpyBeanMultipleClasses {
|
||||
|
||||
}
|
||||
|
||||
@SpyBean(name = "name", classes = { RealExampleService.class,
|
||||
ExampleServiceCaller.class })
|
||||
static class SpyBeanMultipleClassesWithName {
|
||||
|
||||
}
|
||||
|
||||
static class SpyBeanInferClassToMock {
|
||||
|
||||
@SpyBean
|
||||
private RealExampleService exampleService;
|
||||
|
||||
}
|
||||
|
||||
@SpyBean
|
||||
static class SpyBeanMissingClassToMock {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -36,7 +36,7 @@ import static org.mockito.BDDMockito.given;
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
public class OnConfigurationClassForExistingBeanIntegrationTests {
|
||||
public class MockBeanOnConfigurationClassForExistingBeanIntegrationTests {
|
||||
|
||||
@Autowired
|
||||
private ExampleServiceCaller caller;
|
||||
@@ -36,7 +36,7 @@ import static org.mockito.BDDMockito.given;
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
public class OnConfigurationClassForNewBeanIntegrationTests {
|
||||
public class MockBeanOnConfigurationClassForNewBeanIntegrationTests {
|
||||
|
||||
@Autowired
|
||||
private ExampleServiceCaller caller;
|
||||
@@ -37,7 +37,7 @@ import static org.mockito.BDDMockito.given;
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
public class OnConfigurationFieldForExistingBeanIntegrationTests {
|
||||
public class MockBeanOnConfigurationFieldForExistingBeanIntegrationTests {
|
||||
|
||||
@Autowired
|
||||
private Config config;
|
||||
@@ -36,7 +36,7 @@ import static org.mockito.BDDMockito.given;
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
public class OnConfigurationFieldForNewBeanIntegrationTests {
|
||||
public class MockBeanOnConfigurationFieldForNewBeanIntegrationTests {
|
||||
|
||||
@Autowired
|
||||
private Config config;
|
||||
@@ -21,8 +21,8 @@ import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.mock.mockito.OnContextHierarchyIntegrationTests.ChildConfig;
|
||||
import org.springframework.boot.test.mock.mockito.OnContextHierarchyIntegrationTests.ParentConfig;
|
||||
import org.springframework.boot.test.mock.mockito.MockBeanOnContextHierarchyIntegrationTests.ChildConfig;
|
||||
import org.springframework.boot.test.mock.mockito.MockBeanOnContextHierarchyIntegrationTests.ParentConfig;
|
||||
import org.springframework.boot.test.mock.mockito.example.ExampleService;
|
||||
import org.springframework.boot.test.mock.mockito.example.ExampleServiceCaller;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
@@ -42,7 +42,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
@RunWith(SpringRunner.class)
|
||||
@ContextHierarchy({ @ContextConfiguration(classes = ParentConfig.class),
|
||||
@ContextConfiguration(classes = ChildConfig.class) })
|
||||
public class OnContextHierarchyIntegrationTests {
|
||||
public class MockBeanOnContextHierarchyIntegrationTests {
|
||||
|
||||
@Autowired
|
||||
private ChildConfig childConfig;
|
||||
@@ -37,7 +37,7 @@ import static org.mockito.BDDMockito.given;
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@MockBean(ExampleService.class)
|
||||
public class OnTestClassForExistingBeanIntegrationTests {
|
||||
public class MockBeanOnTestClassForExistingBeanIntegrationTests {
|
||||
|
||||
@Autowired
|
||||
private ExampleServiceCaller caller;
|
||||
@@ -36,7 +36,7 @@ import static org.mockito.BDDMockito.given;
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@MockBean(ExampleService.class)
|
||||
public class OnTestClassForNewBeanIntegrationTests {
|
||||
public class MockBeanOnTestClassForNewBeanIntegrationTests {
|
||||
|
||||
@Autowired
|
||||
private ExampleServiceCaller caller;
|
||||
@@ -31,15 +31,15 @@ import static org.mockito.BDDMockito.given;
|
||||
/**
|
||||
* Test {@link MockBean} on a test class field can be used to replace existing beans when
|
||||
* the context is cached. This test is identical to
|
||||
* {@link OnTestFieldForExistingBeanCacheIntegrationTests} so one of them should trigger
|
||||
* application context caching.
|
||||
* {@link MockBeanOnTestFieldForExistingBeanIntegrationTests} so one of them should
|
||||
* trigger application context caching.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @see OnTestFieldForExistingBeanIntegrationTests
|
||||
* @see MockBeanOnTestFieldForExistingBeanIntegrationTests
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@ContextConfiguration(classes = OnTestFieldForExistingBeanConfig.class)
|
||||
public class OnTestFieldForExistingBeanCacheIntegrationTests {
|
||||
@ContextConfiguration(classes = MockBeanOnTestFieldForExistingBeanConfig.class)
|
||||
public class MockBeanOnTestFieldForExistingBeanCacheIntegrationTests {
|
||||
|
||||
@MockBean
|
||||
private ExampleService exampleService;
|
||||
@@ -21,14 +21,14 @@ import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
/**
|
||||
* Config for {@link OnTestFieldForExistingBeanIntegrationTests} and
|
||||
* {@link OnTestFieldForExistingBeanCacheIntegrationTests}. Extracted to a shared config
|
||||
* Config for {@link MockBeanOnTestFieldForExistingBeanIntegrationTests} and
|
||||
* {@link MockBeanOnTestFieldForExistingBeanCacheIntegrationTests}. Extracted to a shared config
|
||||
* to trigger caching.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
@Configuration
|
||||
@Import(ExampleServiceCaller.class)
|
||||
public class OnTestFieldForExistingBeanConfig {
|
||||
public class MockBeanOnTestFieldForExistingBeanConfig {
|
||||
|
||||
}
|
||||
@@ -32,11 +32,11 @@ import static org.mockito.BDDMockito.given;
|
||||
* Test {@link MockBean} on a test class field can be used to replace existing beans.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @see OnTestFieldForExistingBeanCacheIntegrationTests
|
||||
* @see MockBeanOnTestFieldForExistingBeanCacheIntegrationTests
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@ContextConfiguration(classes = OnTestFieldForExistingBeanConfig.class)
|
||||
public class OnTestFieldForExistingBeanIntegrationTests {
|
||||
@ContextConfiguration(classes = MockBeanOnTestFieldForExistingBeanConfig.class)
|
||||
public class MockBeanOnTestFieldForExistingBeanIntegrationTests {
|
||||
|
||||
@MockBean
|
||||
private ExampleService exampleService;
|
||||
@@ -36,7 +36,7 @@ import static org.mockito.BDDMockito.given;
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
public class OnTestFieldForNewBeanIntegrationTests {
|
||||
public class MockBeanOnTestFieldForNewBeanIntegrationTests {
|
||||
|
||||
@MockBean
|
||||
private ExampleService exampleService;
|
||||
@@ -1,184 +0,0 @@
|
||||
/*
|
||||
* Copyright 2012-2016 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
|
||||
*
|
||||
* http://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.boot.test.mock.mockito;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.mockito.Answers;
|
||||
|
||||
import org.springframework.boot.test.mock.mockito.example.ExampleExtraInterface;
|
||||
import org.springframework.boot.test.mock.mockito.example.ExampleService;
|
||||
import org.springframework.boot.test.mock.mockito.example.ExampleServiceCaller;
|
||||
import org.springframework.boot.test.mock.mockito.example.MyMockBean;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link MockDefinitionsParser}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class MockDefinitionsParserTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
private MockDefinitionsParser parser = new MockDefinitionsParser();
|
||||
|
||||
@Test
|
||||
public void parseSingleMockBean() {
|
||||
this.parser.parse(SingleMockBean.class);
|
||||
assertThat(getDefinitions()).hasSize(1);
|
||||
assertThat(getDefinition(0).getClassToMock()).isEqualTo(ExampleService.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseRepeatMockBean() {
|
||||
this.parser.parse(RepeatMockBean.class);
|
||||
assertThat(getDefinitions()).hasSize(2);
|
||||
assertThat(getDefinition(0).getClassToMock()).isEqualTo(ExampleService.class);
|
||||
assertThat(getDefinition(1).getClassToMock())
|
||||
.isEqualTo(ExampleServiceCaller.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore // See SPR-13973
|
||||
public void parseMetaMockBean() {
|
||||
this.parser.parse(MetaMockBean.class);
|
||||
assertThat(getDefinitions()).hasSize(1);
|
||||
assertThat(getDefinition(0).getClassToMock()).isEqualTo(ExampleService.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseMockBeanAttributes() throws Exception {
|
||||
this.parser.parse(MockBeanAttributes.class);
|
||||
assertThat(getDefinitions()).hasSize(1);
|
||||
MockDefinition definition = getDefinition(0);
|
||||
assertThat(definition.getName()).isEqualTo("Name");
|
||||
assertThat(definition.getClassToMock()).isEqualTo(ExampleService.class);
|
||||
assertThat(definition.getExtraInterfaces())
|
||||
.containsExactly(ExampleExtraInterface.class);
|
||||
assertThat(definition.getAnswer()).isEqualTo(Answers.RETURNS_SMART_NULLS);
|
||||
assertThat(definition.isSerializable()).isEqualTo(true);
|
||||
assertThat(definition.getReset()).isEqualTo(MockReset.NONE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseOnClassAndField() throws Exception {
|
||||
this.parser.parse(OnClassAndField.class);
|
||||
assertThat(getDefinitions()).hasSize(2);
|
||||
assertThat(getDefinition(0).getClassToMock()).isEqualTo(ExampleService.class);
|
||||
assertThat(getDefinition(1).getClassToMock())
|
||||
.isEqualTo(ExampleServiceCaller.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseInferClassToMock() throws Exception {
|
||||
this.parser.parse(InferClassToMock.class);
|
||||
assertThat(getDefinitions()).hasSize(1);
|
||||
assertThat(getDefinition(0).getClassToMock()).isEqualTo(ExampleService.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseMissingClassToMock() throws Exception {
|
||||
this.thrown.expect(IllegalStateException.class);
|
||||
this.thrown.expectMessage("Unable to deduce class to mock");
|
||||
this.parser.parse(MissingClassToMock.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseMultipleClasses() throws Exception {
|
||||
this.parser.parse(MultipleClasses.class);
|
||||
assertThat(getDefinitions()).hasSize(2);
|
||||
assertThat(getDefinition(0).getClassToMock()).isEqualTo(ExampleService.class);
|
||||
assertThat(getDefinition(1).getClassToMock())
|
||||
.isEqualTo(ExampleServiceCaller.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseMultipleClassesWithName() throws Exception {
|
||||
this.thrown.expect(IllegalStateException.class);
|
||||
this.thrown.expectMessage(
|
||||
"The name attribute can only be used when mocking a single class");
|
||||
this.parser.parse(MultipleClassesWithName.class);
|
||||
}
|
||||
|
||||
private MockDefinition getDefinition(int index) {
|
||||
return getDefinitions().get(index);
|
||||
}
|
||||
|
||||
private List<MockDefinition> getDefinitions() {
|
||||
return new ArrayList<MockDefinition>(this.parser.getDefinitions());
|
||||
}
|
||||
|
||||
@MockBean(ExampleService.class)
|
||||
static class SingleMockBean {
|
||||
|
||||
}
|
||||
|
||||
@MockBeans({ @MockBean(ExampleService.class), @MockBean(ExampleServiceCaller.class) })
|
||||
static class RepeatMockBean {
|
||||
|
||||
}
|
||||
|
||||
@MyMockBean(ExampleService.class)
|
||||
static class MetaMockBean {
|
||||
|
||||
}
|
||||
|
||||
@MockBean(name = "Name", classes = ExampleService.class, extraInterfaces = ExampleExtraInterface.class, answer = Answers.RETURNS_SMART_NULLS, serializable = true, reset = MockReset.NONE)
|
||||
static class MockBeanAttributes {
|
||||
|
||||
}
|
||||
|
||||
@MockBean(ExampleService.class)
|
||||
static class OnClassAndField {
|
||||
|
||||
@MockBean(ExampleServiceCaller.class)
|
||||
private Object caller;
|
||||
|
||||
}
|
||||
|
||||
@MockBean({ ExampleService.class, ExampleServiceCaller.class })
|
||||
static class MultipleClasses {
|
||||
|
||||
}
|
||||
|
||||
@MockBean(name = "name", classes = { ExampleService.class,
|
||||
ExampleServiceCaller.class })
|
||||
static class MultipleClassesWithName {
|
||||
|
||||
}
|
||||
|
||||
static class InferClassToMock {
|
||||
|
||||
@MockBean
|
||||
private ExampleService exampleService;
|
||||
|
||||
}
|
||||
|
||||
@MockBean
|
||||
static class MissingClassToMock {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -37,13 +37,13 @@ import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* Tests for {@link MockitoInitializeTestExecutionListener}.
|
||||
* Tests for {@link MockitoTestExecutionListener}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class MockitoInitializeTestExecutionListenerTests {
|
||||
|
||||
private MockitoInitializeTestExecutionListener listener = new MockitoInitializeTestExecutionListener();
|
||||
private MockitoTestExecutionListener listener = new MockitoTestExecutionListener();
|
||||
|
||||
@Mock
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
@@ -27,8 +27,7 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* Test for {@link MockitoPostProcessor}. See also the integration tests in the
|
||||
* {@code runner} package.
|
||||
* Test for {@link MockitoPostProcessor}. See also the integration tests.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2012-2016 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
|
||||
*
|
||||
* http://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.boot.test.mock.mockito;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.mock.mockito.example.ExampleServiceCaller;
|
||||
import org.springframework.boot.test.mock.mockito.example.SimpleExampleService;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* Test {@link SpyBean} on a configuration class can be used to spy existing beans.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
public class SpyBeanOnConfigurationClassForExistingBeanIntegrationTests {
|
||||
|
||||
@Autowired
|
||||
private ExampleServiceCaller caller;
|
||||
|
||||
@Test
|
||||
public void testSpying() throws Exception {
|
||||
assertThat(this.caller.sayGreeting()).isEqualTo("I say simple");
|
||||
verify(this.caller.getService()).greeting();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@SpyBean(SimpleExampleService.class)
|
||||
@Import({ ExampleServiceCaller.class, SimpleExampleService.class })
|
||||
static class Config {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2012-2016 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
|
||||
*
|
||||
* http://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.boot.test.mock.mockito;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.mock.mockito.example.ExampleServiceCaller;
|
||||
import org.springframework.boot.test.mock.mockito.example.SimpleExampleService;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* Test {@link SpyBean} on a configuration class can be used to inject new spy instances.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
public class SpyBeanOnConfigurationClassForNewBeanIntegrationTests {
|
||||
|
||||
@Autowired
|
||||
private ExampleServiceCaller caller;
|
||||
|
||||
@Test
|
||||
public void testSpying() throws Exception {
|
||||
assertThat(this.caller.sayGreeting()).isEqualTo("I say simple");
|
||||
verify(this.caller.getService()).greeting();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@SpyBean(SimpleExampleService.class)
|
||||
@Import(ExampleServiceCaller.class)
|
||||
static class Config {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2012-2016 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
|
||||
*
|
||||
* http://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.boot.test.mock.mockito;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.mock.mockito.example.ExampleService;
|
||||
import org.springframework.boot.test.mock.mockito.example.ExampleServiceCaller;
|
||||
import org.springframework.boot.test.mock.mockito.example.SimpleExampleService;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* Test {@link SpyBean} on a field on a {@code @Configuration} class can be used to
|
||||
* replace existing beans.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
public class SpyBeanOnConfigurationFieldForExistingBeanIntegrationTests {
|
||||
|
||||
@Autowired
|
||||
private Config config;
|
||||
|
||||
@Autowired
|
||||
private ExampleServiceCaller caller;
|
||||
|
||||
@Test
|
||||
public void testSpying() throws Exception {
|
||||
assertThat(this.caller.sayGreeting()).isEqualTo("I say simple");
|
||||
verify(this.config.exampleService).greeting();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Import({ ExampleServiceCaller.class, SimpleExampleService.class })
|
||||
static class Config {
|
||||
|
||||
@SpyBean
|
||||
private ExampleService exampleService;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2012-2016 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
|
||||
*
|
||||
* http://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.boot.test.mock.mockito;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.mock.mockito.example.ExampleServiceCaller;
|
||||
import org.springframework.boot.test.mock.mockito.example.SimpleExampleService;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* Test {@link SpyBean} on a field on a {@code @Configuration} class can be used to inject
|
||||
* new spy instances.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
public class SpyBeanOnConfigurationFieldForNewBeanIntegrationTests {
|
||||
|
||||
@Autowired
|
||||
private Config config;
|
||||
|
||||
@Autowired
|
||||
private ExampleServiceCaller caller;
|
||||
|
||||
@Test
|
||||
public void testSpying() throws Exception {
|
||||
assertThat(this.caller.sayGreeting()).isEqualTo("I say simple");
|
||||
verify(this.config.exampleService).greeting();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Import(ExampleServiceCaller.class)
|
||||
static class Config {
|
||||
|
||||
@SpyBean
|
||||
private SimpleExampleService exampleService;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright 2012-2016 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
|
||||
*
|
||||
* http://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.boot.test.mock.mockito;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.mock.mockito.SpyBeanOnContextHierarchyIntegrationTests.ChildConfig;
|
||||
import org.springframework.boot.test.mock.mockito.SpyBeanOnContextHierarchyIntegrationTests.ParentConfig;
|
||||
import org.springframework.boot.test.mock.mockito.example.ExampleService;
|
||||
import org.springframework.boot.test.mock.mockito.example.ExampleServiceCaller;
|
||||
import org.springframework.boot.test.mock.mockito.example.SimpleExampleService;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.ContextHierarchy;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Test {@link SpyBean} can be used with a {@link ContextHierarchy}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@ContextHierarchy({ @ContextConfiguration(classes = ParentConfig.class),
|
||||
@ContextConfiguration(classes = ChildConfig.class) })
|
||||
public class SpyBeanOnContextHierarchyIntegrationTests {
|
||||
|
||||
@Autowired
|
||||
private ChildConfig childConfig;
|
||||
|
||||
@Test
|
||||
public void testSpying() throws Exception {
|
||||
ApplicationContext context = this.childConfig.getContext();
|
||||
ApplicationContext parentContext = context.getParent();
|
||||
assertThat(parentContext.getBeanNamesForType(ExampleService.class)).hasSize(1);
|
||||
assertThat(parentContext.getBeanNamesForType(ExampleServiceCaller.class))
|
||||
.hasSize(0);
|
||||
assertThat(context.getBeanNamesForType(ExampleService.class)).hasSize(0);
|
||||
assertThat(context.getBeanNamesForType(ExampleServiceCaller.class)).hasSize(1);
|
||||
assertThat(context.getBean(ExampleService.class)).isNotNull();
|
||||
assertThat(context.getBean(ExampleServiceCaller.class)).isNotNull();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@SpyBean(SimpleExampleService.class)
|
||||
static class ParentConfig {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@SpyBean(ExampleServiceCaller.class)
|
||||
static class ChildConfig implements ApplicationContextAware {
|
||||
|
||||
private ApplicationContext context;
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext)
|
||||
throws BeansException {
|
||||
this.context = applicationContext;
|
||||
}
|
||||
|
||||
public ApplicationContext getContext() {
|
||||
return this.context;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2012-2016 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
|
||||
*
|
||||
* http://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.boot.test.mock.mockito;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.mock.mockito.example.ExampleServiceCaller;
|
||||
import org.springframework.boot.test.mock.mockito.example.SimpleExampleService;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* Test {@link SpyBean} on a test class can be used to replace existing beans.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpyBean(SimpleExampleService.class)
|
||||
public class SpyBeanOnTestClassForExistingBeanIntegrationTests {
|
||||
|
||||
@Autowired
|
||||
private ExampleServiceCaller caller;
|
||||
|
||||
@Test
|
||||
public void testSpying() throws Exception {
|
||||
assertThat(this.caller.sayGreeting()).isEqualTo("I say simple");
|
||||
verify(this.caller.getService()).greeting();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Import({ ExampleServiceCaller.class, SimpleExampleService.class })
|
||||
static class Config {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2012-2016 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
|
||||
*
|
||||
* http://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.boot.test.mock.mockito;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.mock.mockito.example.ExampleServiceCaller;
|
||||
import org.springframework.boot.test.mock.mockito.example.SimpleExampleService;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* Test {@link SpyBean} on a test class can be used to inject new mock instances.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpyBean(SimpleExampleService.class)
|
||||
public class SpyBeanOnTestClassForNewBeanIntegrationTests {
|
||||
|
||||
@Autowired
|
||||
private ExampleServiceCaller caller;
|
||||
|
||||
@Test
|
||||
public void testSpying() throws Exception {
|
||||
assertThat(this.caller.sayGreeting()).isEqualTo("I say simple");
|
||||
verify(this.caller.getService()).greeting();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Import(ExampleServiceCaller.class)
|
||||
static class Config {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2012-2016 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
|
||||
*
|
||||
* http://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.boot.test.mock.mockito;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.mock.mockito.example.ExampleServiceCaller;
|
||||
import org.springframework.boot.test.mock.mockito.example.SimpleExampleService;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* Test {@link SpyBean} on a test class field can be used to replace existing beans when
|
||||
* the context is cached. This test is identical to
|
||||
* {@link SpyBeanOnTestFieldForExistingBeanIntegrationTests} so one of them should trigger
|
||||
* application context caching.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @see SpyBeanOnTestFieldForExistingBeanIntegrationTests
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@ContextConfiguration(classes = SpyBeanOnTestFieldForExistingBeanConfig.class)
|
||||
public class SpyBeanOnTestFieldForExistingBeanCacheIntegrationTests {
|
||||
|
||||
@SpyBean
|
||||
private SimpleExampleService exampleService;
|
||||
|
||||
@Autowired
|
||||
private ExampleServiceCaller caller;
|
||||
|
||||
@Test
|
||||
public void testSpying() throws Exception {
|
||||
assertThat(this.caller.sayGreeting()).isEqualTo("I say simple");
|
||||
verify(this.caller.getService()).greeting();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2012-2016 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
|
||||
*
|
||||
* http://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.boot.test.mock.mockito;
|
||||
|
||||
import org.springframework.boot.test.mock.mockito.example.ExampleServiceCaller;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
/**
|
||||
* Config for {@link SpyBeanOnTestFieldForExistingBeanIntegrationTests} and
|
||||
* {@link SpyBeanOnTestFieldForExistingBeanCacheIntegrationTests}. Extracted to a shared
|
||||
* config to trigger caching.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
@Configuration
|
||||
@Import(ExampleServiceCaller.class)
|
||||
public class SpyBeanOnTestFieldForExistingBeanConfig {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2012-2016 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
|
||||
*
|
||||
* http://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.boot.test.mock.mockito;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.mock.mockito.example.ExampleServiceCaller;
|
||||
import org.springframework.boot.test.mock.mockito.example.SimpleExampleService;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* Test {@link SpyBean} on a test class field can be used to replace existing beans.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @see SpyBeanOnTestFieldForExistingBeanCacheIntegrationTests
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@ContextConfiguration(classes = MockBeanOnTestFieldForExistingBeanConfig.class)
|
||||
public class SpyBeanOnTestFieldForExistingBeanIntegrationTests {
|
||||
|
||||
@SpyBean
|
||||
private SimpleExampleService exampleService;
|
||||
|
||||
@Autowired
|
||||
private ExampleServiceCaller caller;
|
||||
|
||||
@Test
|
||||
public void testSpying() throws Exception {
|
||||
assertThat(this.caller.sayGreeting()).isEqualTo("I say simple");
|
||||
verify(this.caller.getService()).greeting();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2012-2016 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
|
||||
*
|
||||
* http://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.boot.test.mock.mockito;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.mock.mockito.example.ExampleService;
|
||||
import org.springframework.boot.test.mock.mockito.example.ExampleServiceCaller;
|
||||
import org.springframework.boot.test.mock.mockito.example.SimpleExampleService;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* Test {@link SpyBean} on a test class field can be used to inject new mock instances.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
public class SpyBeanOnTestFieldForNewBeanIntegrationTests {
|
||||
|
||||
@SpyBean
|
||||
private ExampleService exampleService;
|
||||
|
||||
@Autowired
|
||||
private ExampleServiceCaller caller;
|
||||
|
||||
@Test
|
||||
public void testSpying() throws Exception {
|
||||
assertThat(this.caller.sayGreeting()).isEqualTo("I say simple");
|
||||
verify(this.caller.getService()).greeting();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Import({ ExampleServiceCaller.class, SimpleExampleService.class })
|
||||
static class Config {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright 2012-2016 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
|
||||
*
|
||||
* http://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.boot.test.mock.mockito;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.mockito.Answers;
|
||||
import org.mockito.internal.util.MockUtil;
|
||||
import org.mockito.mock.MockCreationSettings;
|
||||
|
||||
import org.springframework.boot.test.mock.mockito.example.ExampleService;
|
||||
import org.springframework.boot.test.mock.mockito.example.ExampleServiceCaller;
|
||||
import org.springframework.boot.test.mock.mockito.example.RealExampleService;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link SpyDefinition}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class SpyDefinitionTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
@Test
|
||||
public void ClassToSpyMustNotBeNull() throws Exception {
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("ClassToSpy must not be null");
|
||||
new SpyDefinition(null, null, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createWithDefaults() throws Exception {
|
||||
SpyDefinition definition = new SpyDefinition(null, RealExampleService.class,
|
||||
null);
|
||||
assertThat(definition.getName()).isNull();
|
||||
assertThat(definition.getClassToSpy()).isEqualTo(RealExampleService.class);
|
||||
assertThat(definition.getReset()).isEqualTo(MockReset.AFTER);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createExplicit() throws Exception {
|
||||
SpyDefinition definition = new SpyDefinition("name", RealExampleService.class,
|
||||
MockReset.BEFORE);
|
||||
assertThat(definition.getName()).isEqualTo("name");
|
||||
assertThat(definition.getClassToSpy()).isEqualTo(RealExampleService.class);
|
||||
assertThat(definition.getReset()).isEqualTo(MockReset.BEFORE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createSpy() throws Exception {
|
||||
SpyDefinition definition = new SpyDefinition("name", RealExampleService.class,
|
||||
MockReset.BEFORE);
|
||||
RealExampleService spy = definition.createSpy(new RealExampleService("hello"));
|
||||
MockCreationSettings<?> settings = new MockUtil().getMockSettings(spy);
|
||||
assertThat(spy).isInstanceOf(ExampleService.class);
|
||||
assertThat(settings.getMockName().toString()).isEqualTo("name");
|
||||
assertThat(settings.getDefaultAnswer())
|
||||
.isEqualTo(Answers.CALLS_REAL_METHODS.get());
|
||||
assertThat(MockReset.get(spy)).isEqualTo(MockReset.BEFORE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createSpyWhenNullInstanceShouldThrowException() throws Exception {
|
||||
SpyDefinition definition = new SpyDefinition("name", RealExampleService.class,
|
||||
MockReset.BEFORE);
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("Instance must not be null");
|
||||
definition.createSpy(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createSpyWhenWrongInstanceShouldThrowException() throws Exception {
|
||||
SpyDefinition definition = new SpyDefinition("name", RealExampleService.class,
|
||||
MockReset.BEFORE);
|
||||
this.thrown.expect(IllegalArgumentException.class);
|
||||
this.thrown.expectMessage("must be an instance of");
|
||||
definition.createSpy(new ExampleServiceCaller(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createSpyTwice() throws Exception {
|
||||
SpyDefinition definition = new SpyDefinition("name", RealExampleService.class,
|
||||
MockReset.BEFORE);
|
||||
Object instance = new RealExampleService("hello");
|
||||
instance = definition.createSpy(instance);
|
||||
instance = definition.createSpy(instance);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2012-2016 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
|
||||
*
|
||||
* http://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.boot.test.mock.mockito.example;
|
||||
|
||||
/**
|
||||
* Example service implementation for spy tests.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class RealExampleService implements ExampleService {
|
||||
|
||||
private final String greeting;
|
||||
|
||||
public RealExampleService(String greeting) {
|
||||
this.greeting = greeting;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String greeting() {
|
||||
return this.greeting;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2012-2016 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
|
||||
*
|
||||
* http://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.boot.test.mock.mockito.example;
|
||||
|
||||
/**
|
||||
* Example service implementation for spy tests.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class SimpleExampleService extends RealExampleService {
|
||||
|
||||
public SimpleExampleService() {
|
||||
super("simple");
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user