forked from mockito/mockito
-
Notifications
You must be signed in to change notification settings - Fork 0
/
MockScanner.java
99 lines (87 loc) · 2.87 KB
/
MockScanner.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
/*
* Copyright (c) 2007 Mockito contributors
* This program is made available under the terms of the MIT License.
*/
package org.mockito.internal.configuration.injection.scanner;
import static org.mockito.internal.util.collections.Sets.newMockSafeHashSet;
import java.lang.reflect.Field;
import java.util.Set;
import org.mockito.Mock;
import org.mockito.Spy;
import org.mockito.internal.util.MockUtil;
import org.mockito.internal.util.reflection.FieldReader;
/**
* Scan mocks, and prepare them if needed.
*/
public class MockScanner {
private final Object instance;
private final Class<?> clazz;
/**
* Creates a MockScanner.
*
* @param instance The test instance
* @param clazz The class in the type hierarchy of this instance.
*/
public MockScanner(Object instance, Class<?> clazz) {
this.instance = instance;
this.clazz = clazz;
}
/**
* Add the scanned and prepared mock instance to the given collection.
*
* <p>
* The preparation of mocks consists only in defining a MockName if not already set.
* </p>
*
* @param mocks Set of mocks
*/
public void addPreparedMocks(Set<Object> mocks) {
scan(clazz, mocks);
}
/**
* Scan and prepare mocks for the whole hierarchy of given <code>testClassInstance</code>.
*
* @return A prepared set of mock
*/
public Set<Object> scanHierarchy() {
final Set<Object> mocks = newMockSafeHashSet();
Class<?> currentClass = clazz;
while (currentClass != Object.class) {
scan(currentClass, mocks);
currentClass = currentClass.getSuperclass();
}
return mocks;
}
/**
* Scan and prepare mocks for the given <code>testClassInstance</code> and <code>clazz</code> in the type hierarchy.
*
* @return A prepared set of mock
*/
private void scan(Class<?> clazz, Set<Object> mocks) {
for (Field field : clazz.getDeclaredFields()) {
// mock or spies only
FieldReader fieldReader = new FieldReader(instance, field);
Object mockInstance = preparedMock(fieldReader.read(), field);
if (mockInstance != null) {
mocks.add(mockInstance);
}
}
}
private Object preparedMock(Object instance, Field field) {
if (isAnnotatedByMockOrSpy(field)) {
return instance;
}
if (isMockOrSpy(instance)) {
MockUtil.maybeRedefineMockName(instance, field.getName());
return instance;
}
return null;
}
private boolean isAnnotatedByMockOrSpy(Field field) {
return field.isAnnotationPresent(Spy.class) || field.isAnnotationPresent(Mock.class);
}
private boolean isMockOrSpy(Object instance) {
return MockUtil.isMock(instance)
|| MockUtil.isSpy(instance);
}
}