forked from mockito/mockito
/
UnusedStubbingsFinder.java
73 lines (65 loc) · 3.16 KB
/
UnusedStubbingsFinder.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
/*
* Copyright (c) 2016 Mockito contributors
* This program is made available under the terms of the MIT License.
*/
package org.mockito.internal.junit;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.mockito.internal.invocation.finder.AllInvocationsFinder;
import org.mockito.internal.stubbing.UnusedStubbingReporting;
import org.mockito.invocation.Invocation;
import org.mockito.stubbing.Stubbing;
/**
* Finds unused stubbings
*/
public class UnusedStubbingsFinder {
/**
* Gets all unused stubbings for given set of mock objects, in order.
* Stubbings explicitily marked as LENIENT are not included.
*/
public UnusedStubbings getUnusedStubbings(Iterable<Object> mocks) {
return new UnusedStubbings(
AllInvocationsFinder.findStubbings(mocks).stream()
.filter(UnusedStubbingReporting::shouldBeReported)
.collect(Collectors.toList()));
}
/**
* Gets unused stubbings per location. This method is less accurate than {@link #getUnusedStubbings(Iterable)}.
* It considers that stubbings with the same location (e.g. ClassFile + line number) are the same.
* This is not completely accurate because a stubbing declared in a setup or constructor
* is created per each test method. Because those are different test methods,
* different mocks are created, different 'Invocation' instance is backing the 'Stubbing' instance.
* In certain scenarios (detecting unused stubbings by JUnit runner), we need this exact level of accuracy.
* Stubbing declared in constructor but realized in % of test methods is considered as 'used' stubbing.
* There are high level unit tests that demonstrate this scenario.
*/
public Collection<Invocation> getUnusedStubbingsByLocation(Iterable<Object> mocks) {
Set<Stubbing> stubbings = AllInvocationsFinder.findStubbings(mocks);
// 1st pass, collect all the locations of the stubbings that were used
// note that those are _not_ locations where the stubbings was used
Set<String> locationsOfUsedStubbings = new HashSet<>();
for (Stubbing s : stubbings) {
if (!UnusedStubbingReporting.shouldBeReported(s)) {
String location = s.getInvocation().getLocation().toString();
locationsOfUsedStubbings.add(location);
}
}
// 2nd pass, collect unused stubbings by location
// If the location matches we assume the stubbing was used in at least one test method
// Also, using map to deduplicate reported unused stubbings
// if unused stubbing appear in the setup method / constructor we don't want to report it
// per each test case
Map<String, Invocation> out = new LinkedHashMap<>();
for (Stubbing s : stubbings) {
String location = s.getInvocation().getLocation().toString();
if (!locationsOfUsedStubbings.contains(location)) {
out.put(location, s.getInvocation());
}
}
return out.values();
}
}