4
4
*/
5
5
package org .mockito .testng ;
6
6
7
+ import java .lang .annotation .Annotation ;
8
+ import java .util .Arrays ;
7
9
import java .util .Map ;
8
10
import java .util .Optional ;
9
11
import java .util .WeakHashMap ;
12
+ import java .util .stream .Stream ;
10
13
11
14
import org .mockito .Mockito ;
12
15
import org .mockito .MockitoSession ;
13
16
import org .mockito .quality .Strictness ;
14
17
import org .testng .IInvokedMethod ;
15
18
import org .testng .IInvokedMethodListener ;
16
- import org .testng .ITestNGListener ;
19
+ import org .testng .ITestNGMethod ;
17
20
import org .testng .ITestResult ;
18
21
import org .testng .annotations .Listeners ;
19
22
55
58
* </code></pre>
56
59
*
57
60
* <p>
61
+ * By default {@link MockitoSession} is started with {@link Strictness#STRICT_STUBS}.
62
+ * You can change this behavior by adding {@link MockitoSettings} to your test class.
63
+ * </p>
64
+ *
65
+ * <pre class="code"><code class="java">
66
+ * <b>@Listeners(MockitoTestNGListener.class)</b>
67
+ * <b>@MockitoSettings(strictness = Strictness.WARN)</b>
68
+ * public class ExampleTest {
69
+ * ...
70
+ * }
71
+ * </code></pre>
72
+ *
73
+ * <p>
58
74
* <code>MockitoTestNGListener</code> not working with parallel tests,
59
75
* more information https://github.com/mockito/mockito-testng/issues/20
60
76
* </p>
@@ -65,49 +81,65 @@ public class MockitoTestNGListener implements IInvokedMethodListener {
65
81
66
82
@ Override
67
83
public void beforeInvocation (IInvokedMethod method , ITestResult testResult ) {
68
- if (hasMockitoTestNGListenerInTestHierarchy (testResult )) {
69
- sessions .computeIfAbsent (testResult .getInstance (), testInstance ->
70
- Mockito .mockitoSession ()
71
- .initMocks (testInstance )
72
- .strictness (Strictness .STRICT_STUBS )
73
- .startMocking ()
84
+ if (shouldBeRunBeforeInvocation (method , testResult )) {
85
+ sessions .computeIfAbsent (testResult .getInstance (), testInstance -> {
86
+
87
+ Strictness strictness = findAnnotation (testResult , MockitoSettings .class )
88
+ .map (MockitoSettings ::strictness ).orElse (Strictness .STRICT_STUBS );
89
+
90
+ return Mockito .mockitoSession ()
91
+ .initMocks (testInstance )
92
+ .strictness (strictness )
93
+ .startMocking ();
94
+ }
74
95
);
75
96
}
76
97
}
77
98
78
99
@ Override
79
100
public void afterInvocation (IInvokedMethod method , ITestResult testResult ) {
80
- if (hasMockitoTestNGListenerInTestHierarchy ( testResult ) && method . isTestMethod ( )) {
101
+ if (shouldBeRunAfterInvocation ( method , testResult )) {
81
102
Optional .ofNullable (sessions .remove (testResult .getInstance ()))
82
103
.ifPresent (mockitoSession -> mockitoSession .finishMocking (testResult .getThrowable ()));
83
104
}
84
105
}
85
106
86
- protected boolean hasMockitoTestNGListenerInTestHierarchy (ITestResult testResult ) {
87
- for (Class <?> clazz = testResult .getTestClass ().getRealClass (); clazz != Object .class ; clazz = clazz .getSuperclass ()) {
88
- if (hasMockitoTestNGListener (clazz )) {
89
- return true ;
90
- }
91
- }
92
- return false ;
107
+ private boolean shouldBeRunBeforeInvocation (IInvokedMethod method , ITestResult testResult ) {
108
+ return !isAfterConfigurationMethod (method ) && hasMockitoTestNGListener (testResult );
93
109
}
94
110
95
- protected boolean hasMockitoTestNGListener (Class <?> clazz ) {
96
- Listeners listeners = clazz .getAnnotation (Listeners .class );
97
- if (listeners == null ) {
98
- return false ;
99
- }
111
+ private boolean isAfterConfigurationMethod (IInvokedMethod method ) {
112
+ ITestNGMethod testMethod = method .getTestMethod ();
113
+ return testMethod .isAfterClassConfiguration ()
114
+ || testMethod .isAfterMethodConfiguration ()
115
+ || testMethod .isAfterGroupsConfiguration ()
116
+ || testMethod .isAfterTestConfiguration ()
117
+ || testMethod .isAfterSuiteConfiguration ();
118
+ }
100
119
101
- for (Class <? extends ITestNGListener > listenerClass : listeners .value ()) {
102
- if (listenerClass () == listenerClass ) {
103
- return true ;
104
- }
105
- }
106
- return false ;
120
+ private boolean shouldBeRunAfterInvocation (IInvokedMethod method , ITestResult testResult ) {
121
+ return method .isTestMethod () && hasMockitoTestNGListener (testResult );
107
122
}
108
123
109
- protected Class <MockitoTestNGListener > listenerClass () {
110
- return MockitoTestNGListener .class ;
124
+ protected boolean hasMockitoTestNGListener (ITestResult testResult ) {
125
+
126
+ return findAnnotation (testResult , Listeners .class )
127
+ .map (Listeners ::value )
128
+ .map (Arrays ::stream )
129
+ .orElseGet (Stream ::empty )
130
+ .anyMatch (listener -> listener == MockitoTestNGListener .class );
111
131
}
112
132
133
+ <A extends Annotation > Optional <A > findAnnotation (ITestResult testResult , Class <A > annotationClass ) {
134
+
135
+ for (Class <?> clazz = testResult .getTestClass ().getRealClass ();
136
+ clazz != Object .class ; clazz = clazz .getSuperclass ()) {
137
+ Optional <A > annotation = Optional .ofNullable (clazz .getAnnotation (annotationClass ));
138
+ if (annotation .isPresent ()) {
139
+ return annotation ;
140
+ }
141
+ }
142
+
143
+ return Optional .empty ();
144
+ }
113
145
}
0 commit comments