diff --git a/README.MD b/README.MD
index 5b27ab3..1c0ddcf 100644
--- a/README.MD
+++ b/README.MD
@@ -86,7 +86,7 @@ Simply include the maven dependency (from central maven) to start using @MockInB
com.teketikmock-in-bean
- boot2-v1.0
+ boot2-v1.1test
```
diff --git a/pom.xml b/pom.xml
index 40b06c6..253ab38 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
4.0.0com.teketikmock-in-bean
- boot2-v1.0-SNAPSHOT
+ boot2-v1.1-SNAPSHOTMock in BeanSurgically Inject Mockito Mock/Spy in Spring Beanshttps://github.com/antoinemeyer/mock-in-bean
diff --git a/src/main/java/org/springframework/boot/test/mock/mockito/BeanFieldState.java b/src/main/java/com/teketik/test/mockinbean/BeanFieldState.java
similarity index 81%
rename from src/main/java/org/springframework/boot/test/mock/mockito/BeanFieldState.java
rename to src/main/java/com/teketik/test/mockinbean/BeanFieldState.java
index 345a695..f233eaa 100644
--- a/src/main/java/org/springframework/boot/test/mock/mockito/BeanFieldState.java
+++ b/src/main/java/com/teketik/test/mockinbean/BeanFieldState.java
@@ -1,4 +1,4 @@
-package org.springframework.boot.test.mock.mockito;
+package com.teketik.test.mockinbean;
import org.springframework.test.context.TestContext;
@@ -8,7 +8,7 @@ class BeanFieldState extends FieldState {
private Object bean;
- public BeanFieldState(Object bean, Field field, Object originalValue, DefinitionFacade definition) {
+ public BeanFieldState(Object bean, Field field, Object originalValue, Definition definition) {
super(field, originalValue, definition);
this.bean = bean;
}
diff --git a/src/main/java/org/springframework/boot/test/mock/mockito/BeanUtils.java b/src/main/java/com/teketik/test/mockinbean/BeanUtils.java
similarity index 98%
rename from src/main/java/org/springframework/boot/test/mock/mockito/BeanUtils.java
rename to src/main/java/com/teketik/test/mockinbean/BeanUtils.java
index df71937..eb98844 100644
--- a/src/main/java/org/springframework/boot/test/mock/mockito/BeanUtils.java
+++ b/src/main/java/com/teketik/test/mockinbean/BeanUtils.java
@@ -1,4 +1,4 @@
-package org.springframework.boot.test.mock.mockito;
+package com.teketik.test.mockinbean;
import org.springframework.context.ApplicationContext;
import org.springframework.lang.Nullable;
diff --git a/src/main/java/com/teketik/test/mockinbean/Definition.java b/src/main/java/com/teketik/test/mockinbean/Definition.java
new file mode 100644
index 0000000..737f9be
--- /dev/null
+++ b/src/main/java/com/teketik/test/mockinbean/Definition.java
@@ -0,0 +1,66 @@
+package com.teketik.test.mockinbean;
+
+import org.mockito.Mock;
+import org.mockito.Spy;
+import org.springframework.core.ResolvableType;
+
+import java.util.Objects;
+
+/**
+ *
Definition of a {@link Mock mock} or a {@link Spy spy}.
+ *
Corresponding entity can be created using {@link #create(Object)}.
+ * @author Antoine Meyer
+ */
+abstract class Definition {
+
+ protected final String name;
+ protected final ResolvableType resolvableType;
+
+ Definition(String name, ResolvableType resolvableType) {
+ super();
+ this.name = name;
+ this.resolvableType = resolvableType;
+ }
+
+ String getName() {
+ return name;
+ }
+
+ ResolvableType getResolvableType() {
+ return resolvableType;
+ }
+
+ /**
+ * Creates a mock or a spy of the provided original value.
+ * @param
+ * @param originalValue
+ * @return
+ */
+ abstract T create(Object originalValue);
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name, resolvableType);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ Definition other = (Definition) obj;
+ return Objects.equals(name, other.name) && Objects.equals(resolvableType, other.resolvableType);
+ }
+
+ @Override
+ public String toString() {
+ return "Definition [name=" + name + ", resolvableType=" + resolvableType + "]";
+ }
+
+}
diff --git a/src/main/java/org/springframework/boot/test/mock/mockito/FieldState.java b/src/main/java/com/teketik/test/mockinbean/FieldState.java
similarity index 69%
rename from src/main/java/org/springframework/boot/test/mock/mockito/FieldState.java
rename to src/main/java/com/teketik/test/mockinbean/FieldState.java
index 77885e0..bd3ccb7 100644
--- a/src/main/java/org/springframework/boot/test/mock/mockito/FieldState.java
+++ b/src/main/java/com/teketik/test/mockinbean/FieldState.java
@@ -1,4 +1,4 @@
-package org.springframework.boot.test.mock.mockito;
+package com.teketik.test.mockinbean;
import org.springframework.lang.Nullable;
import org.springframework.test.context.TestContext;
@@ -12,14 +12,14 @@ abstract class FieldState {
@Nullable
final Object originalValue;
- final DefinitionFacade definition;
+ final Definition definition;
- public FieldState(Field targetField, Object originalValue, DefinitionFacade definition) {
+ public FieldState(Field targetField, Object originalValue, Definition definition) {
this.field = targetField;
this.originalValue = originalValue;
this.definition = definition;
}
- public abstract Object resolveTarget(TestContext testContext);
+ abstract Object resolveTarget(TestContext testContext);
}
diff --git a/src/main/java/org/springframework/boot/test/mock/mockito/InBeanDefinition.java b/src/main/java/com/teketik/test/mockinbean/InBeanDefinition.java
similarity index 64%
rename from src/main/java/org/springframework/boot/test/mock/mockito/InBeanDefinition.java
rename to src/main/java/com/teketik/test/mockinbean/InBeanDefinition.java
index 4d6bfa1..10102e1 100644
--- a/src/main/java/org/springframework/boot/test/mock/mockito/InBeanDefinition.java
+++ b/src/main/java/com/teketik/test/mockinbean/InBeanDefinition.java
@@ -1,7 +1,4 @@
-package org.springframework.boot.test.mock.mockito;
-
-import com.teketik.test.mockinbean.MockInBean;
-import com.teketik.test.mockinbean.SpyInBean;
+package com.teketik.test.mockinbean;
import org.springframework.lang.Nullable;
@@ -16,7 +13,7 @@ class InBeanDefinition {
@Nullable
final String name;
- public InBeanDefinition(Class> clazz, String name) {
+ InBeanDefinition(Class> clazz, String name) {
super();
this.clazz = clazz;
this.name = name;
diff --git a/src/main/java/org/springframework/boot/test/mock/mockito/InBeanDefinitionsParser.java b/src/main/java/com/teketik/test/mockinbean/InBeanDefinitionsParser.java
similarity index 73%
rename from src/main/java/org/springframework/boot/test/mock/mockito/InBeanDefinitionsParser.java
rename to src/main/java/com/teketik/test/mockinbean/InBeanDefinitionsParser.java
index 880cc94..17c31a3 100644
--- a/src/main/java/org/springframework/boot/test/mock/mockito/InBeanDefinitionsParser.java
+++ b/src/main/java/com/teketik/test/mockinbean/InBeanDefinitionsParser.java
@@ -1,7 +1,4 @@
-package org.springframework.boot.test.mock.mockito;
-
-import com.teketik.test.mockinbean.MockInBean;
-import com.teketik.test.mockinbean.SpyInBean;
+package com.teketik.test.mockinbean;
import org.springframework.core.ResolvableType;
import org.springframework.core.annotation.MergedAnnotation;
@@ -23,13 +20,13 @@
import java.util.Set;
/**
- *
Similar to {@link DefinitionsParser} but handles {@link MockInBean} and {@link SpyInBean}.
+ *
Similar to {@link org.springframework.boot.test.mock.mockito.DefinitionsParser} but handles {@link MockInBean} and {@link SpyInBean}.
*
Every mock/spy {@link Definition} maps to one or more {@link InBeanDefinition}.
* @see DefinitionsParser
*/
class InBeanDefinitionsParser {
- private final Map> definitions = new HashMap>();
+ private final Map> definitions = new HashMap>();
void parse(Class> source) {
ReflectionUtils.doWithFields(source, (field) -> parseField(field, source));
@@ -51,12 +48,15 @@ private void parseMockInBeanAnnotation(MockInBean annotation, Field field, Class
final Set typesToMock = getOrDeduceTypes(field, source);
Assert.state(!typesToMock.isEmpty(), () -> "Unable to deduce type to mock from " + field);
for (ResolvableType typeToMock : typesToMock) {
- final MockDefinition mockDefinition = new MockDefinition(field.getName(), typeToMock, new Class[] {}, null, false, MockReset.AFTER, QualifierDefinition.forElement(field));
- InBeanDefinition inBeanDefinition = new InBeanDefinition(
+ final Definition definition = new MockDefinition(
+ field.getName(),
+ typeToMock
+ );
+ final InBeanDefinition inBeanDefinition = new InBeanDefinition(
annotation.value(),
StringUtils.isEmpty(annotation.name()) ? null : annotation.name()
);
- addDefinition(mockDefinition, inBeanDefinition);
+ addDefinition(definition, inBeanDefinition);
}
}
@@ -64,20 +64,19 @@ private void parseSpyInBeanAnnotation(SpyInBean annotation, Field field, Class
final Set typesToSpy = getOrDeduceTypes(field, source);
Assert.state(!typesToSpy.isEmpty(), () -> "Unable to deduce type to spy from " + field);
for (ResolvableType typeToSpy : typesToSpy) {
- final SpyDefinition spyDefinition = new SpyDefinition(field.getName(), typeToSpy, MockReset.AFTER, true, QualifierDefinition.forElement(field));
- InBeanDefinition inBeanDefinition = new InBeanDefinition(
+ final Definition definition = new SpyDefinition(
+ field.getName(),
+ typeToSpy
+ );
+ final InBeanDefinition inBeanDefinition = new InBeanDefinition(
annotation.value(),
StringUtils.isEmpty(annotation.name()) ? null : annotation.name()
);
- addDefinition(spyDefinition, inBeanDefinition);
+ addDefinition(definition, inBeanDefinition);
}
}
private void addDefinition(Definition definition, InBeanDefinition inBeanDefinition) {
- addDefinition(new DefinitionFacade(definition), inBeanDefinition);
- }
-
- private void addDefinition(DefinitionFacade definition, InBeanDefinition inBeanDefinition) {
List inBeanBaseDefinitions = definitions.get(definition);
if (inBeanBaseDefinitions == null) {
inBeanBaseDefinitions = new LinkedList();
@@ -99,7 +98,7 @@ private Set getOrDeduceTypes(AnnotatedElement element, Class>
return types;
}
- public Map> getDefinitions() {
+ public Map> getDefinitions() {
return Collections.unmodifiableMap(definitions);
}
diff --git a/src/main/java/com/teketik/test/mockinbean/MockDefinition.java b/src/main/java/com/teketik/test/mockinbean/MockDefinition.java
new file mode 100644
index 0000000..55667e3
--- /dev/null
+++ b/src/main/java/com/teketik/test/mockinbean/MockDefinition.java
@@ -0,0 +1,22 @@
+package com.teketik.test.mockinbean;
+
+import static org.mockito.Mockito.mock;
+
+import org.mockito.MockSettings;
+import org.springframework.boot.test.mock.mockito.MockReset;
+import org.springframework.core.ResolvableType;
+
+class MockDefinition extends Definition {
+
+ MockDefinition(String name, ResolvableType type) {
+ super(name, type);
+ }
+
+ @Override
+ T create(Object originalValue) {
+ MockSettings settings = MockReset.withSettings(MockReset.AFTER);
+ settings.name(name);
+ return (T) mock(resolvableType.resolve(), settings);
+ }
+
+}
diff --git a/src/main/java/org/springframework/boot/test/mock/mockito/MockInBeanTestExecutionListener.java b/src/main/java/com/teketik/test/mockinbean/MockInBeanTestExecutionListener.java
similarity index 90%
rename from src/main/java/org/springframework/boot/test/mock/mockito/MockInBeanTestExecutionListener.java
rename to src/main/java/com/teketik/test/mockinbean/MockInBeanTestExecutionListener.java
index 52b985e..fe72444 100644
--- a/src/main/java/org/springframework/boot/test/mock/mockito/MockInBeanTestExecutionListener.java
+++ b/src/main/java/com/teketik/test/mockinbean/MockInBeanTestExecutionListener.java
@@ -1,4 +1,4 @@
-package org.springframework.boot.test.mock.mockito;
+package com.teketik.test.mockinbean;
import org.mockito.Mock;
import org.mockito.Spy;
@@ -38,9 +38,9 @@ public void beforeTestClass(TestContext testContext) throws Exception {
parser.parse(testContext.getTestClass());
final Set visitedFields = new HashSet<>();
final LinkedList originalValues = new LinkedList<>();
- for (Entry> definitionToInbeans : parser.getDefinitions().entrySet()) {
- final DefinitionFacade definition = definitionToInbeans.getKey();
- final Class> mockOrSpyType = definition.getType();
+ for (Entry> definitionToInbeans : parser.getDefinitions().entrySet()) {
+ final Definition definition = definitionToInbeans.getKey();
+ final Class> mockOrSpyType = (Class>) definition.getResolvableType().getType();
Field beanField = null;
for (InBeanDefinition inBeanDefinition : definitionToInbeans.getValue()) {
beanField = BeanUtils.findField(inBeanDefinition.clazz, definition.getName(), mockOrSpyType);
@@ -79,12 +79,12 @@ public void beforeTestClass(TestContext testContext) throws Exception {
*/
@Override
public void beforeTestMethod(TestContext testContext) throws Exception {
- final Map mockOrSpys = new HashMap<>();
+ final Map mockOrSpys = new HashMap<>();
((LinkedList) testContext.getAttribute(ORIGINAL_VALUES_ATTRIBUTE_NAME))
.forEach(fieldState -> {
Object mockOrSpy = mockOrSpys.get(fieldState.definition);
if (mockOrSpy == null) {
- mockOrSpy = fieldState.definition.makeMockOrSpy(fieldState.originalValue);
+ mockOrSpy = fieldState.definition.create(fieldState.originalValue);
mockOrSpys.put(fieldState.definition, mockOrSpy);
}
ReflectionUtils.setField(
diff --git a/src/main/java/com/teketik/test/mockinbean/SpyDefinition.java b/src/main/java/com/teketik/test/mockinbean/SpyDefinition.java
new file mode 100644
index 0000000..30aeacd
--- /dev/null
+++ b/src/main/java/com/teketik/test/mockinbean/SpyDefinition.java
@@ -0,0 +1,27 @@
+package com.teketik.test.mockinbean;
+
+import org.mockito.MockSettings;
+import org.mockito.Mockito;
+import org.springframework.boot.test.mock.mockito.MockReset;
+import org.springframework.core.ResolvableType;
+import org.springframework.util.Assert;
+
+class SpyDefinition extends Definition {
+
+ SpyDefinition(String name, ResolvableType type) {
+ super(name, type);
+ }
+
+ @Override
+ T create(Object originalValue) {
+ Assert.notNull(originalValue, "originalValue must not be null");
+ Assert.isInstanceOf(this.resolvableType.resolve(), originalValue);
+ Assert.state(!Mockito.mockingDetails(originalValue).isSpy(), "originalValue is already a spy");
+ MockSettings settings = MockReset.withSettings(MockReset.AFTER);
+ settings.name(name);
+ settings.spiedInstance(originalValue);
+ settings.defaultAnswer(Mockito.CALLS_REAL_METHODS);
+ return (T) Mockito.mock(originalValue.getClass(), settings);
+ }
+
+}
diff --git a/src/main/java/org/springframework/boot/test/mock/mockito/TestFieldState.java b/src/main/java/com/teketik/test/mockinbean/TestFieldState.java
similarity index 55%
rename from src/main/java/org/springframework/boot/test/mock/mockito/TestFieldState.java
rename to src/main/java/com/teketik/test/mockinbean/TestFieldState.java
index f322dc9..512f371 100644
--- a/src/main/java/org/springframework/boot/test/mock/mockito/TestFieldState.java
+++ b/src/main/java/com/teketik/test/mockinbean/TestFieldState.java
@@ -1,4 +1,4 @@
-package org.springframework.boot.test.mock.mockito;
+package com.teketik.test.mockinbean;
import org.springframework.test.context.TestContext;
@@ -6,12 +6,12 @@
class TestFieldState extends FieldState {
- public TestFieldState(Field targetField, Object originalValue, DefinitionFacade definition) {
+ TestFieldState(Field targetField, Object originalValue, Definition definition) {
super(targetField, originalValue, definition);
}
@Override
- public Object resolveTarget(TestContext testContext) {
+ Object resolveTarget(TestContext testContext) {
return testContext.getTestInstance();
}
diff --git a/src/main/java/org/springframework/boot/test/mock/mockito/DefinitionFacade.java b/src/main/java/org/springframework/boot/test/mock/mockito/DefinitionFacade.java
deleted file mode 100644
index a06a769..0000000
--- a/src/main/java/org/springframework/boot/test/mock/mockito/DefinitionFacade.java
+++ /dev/null
@@ -1,66 +0,0 @@
-package org.springframework.boot.test.mock.mockito;
-
-import java.util.Objects;
-import java.util.function.Function;
-
-/**
- *
{@link Definition} facade exposing common methods for {@link MockDefinition} and {@link SpyDefinition}.
- * @author Antoine Meyer
- */
-class DefinitionFacade {
-
- private final Definition definition;
- private final Class> type;
- private final Function