• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.modules.utils.testing;
17 
18 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
19 
20 import static com.google.common.truth.Truth.assertWithMessage;
21 
22 import static org.junit.Assert.assertThrows;
23 import static org.mockito.ArgumentMatchers.any;
24 import static org.mockito.ArgumentMatchers.notNull;
25 import static org.mockito.Mockito.doThrow;
26 import static org.mockito.Mockito.inOrder;
27 import static org.mockito.Mockito.verify;
28 import static org.mockito.Mockito.when;
29 
30 import android.util.Log;
31 
32 import androidx.annotation.Nullable;
33 
34 import com.android.modules.utils.testing.ExtendedMockitoRule.MockStatic;
35 import com.android.modules.utils.testing.ExtendedMockitoRule.SpyStatic;
36 
37 import org.junit.Test;
38 import org.junit.runner.Description;
39 import org.junit.runner.RunWith;
40 import org.junit.runners.model.Statement;
41 import org.mockito.InOrder;
42 import org.mockito.Mock;
43 import org.mockito.Mockito;
44 import org.mockito.MockitoFramework;
45 import org.mockito.MockitoSession;
46 import org.mockito.exceptions.misusing.UnnecessaryStubbingException;
47 import org.mockito.invocation.InvocationFactory;
48 import org.mockito.junit.MockitoJUnitRunner;
49 import org.mockito.listeners.MockitoListener;
50 import org.mockito.plugins.MockitoPlugins;
51 import org.mockito.quality.Strictness;
52 
53 import java.lang.annotation.Annotation;
54 import java.util.Collection;
55 import java.util.Objects;
56 import java.util.Set;
57 import java.util.function.Supplier;
58 
59 @RunWith(MockitoJUnitRunner.class)
60 public final class ExtendedMockitoRuleTest {
61 
62     public static final String TAG = ExtendedMockitoRuleTest.class.getSimpleName();
63 
64     // Not a real test (i.e., it doesn't exist on this class), but it's passed to Description
65     private static final String TEST_METHOD_BEING_EXECUTED = "testAmI..OrNot";
66 
67     private @Mock Statement mStatement;
68     private @Mock Runnable mRunnable;
69     private @Mock StaticMockFixture mStaticMockFixture1;
70     private @Mock StaticMockFixture mStaticMockFixture2;
71     private @Mock StaticMockFixture mStaticMockFixture3;
72 
73     private final Description mDescription = newTestMethod();
74     private final ClassUnderTest mClassUnderTest = new ClassUnderTest();
75     private final ExtendedMockitoRule.Builder mBuilder =
76             new ExtendedMockitoRule.Builder(mClassUnderTest);
77     // Builder that doesn't clear inline methods at the end - should be used in methods that
78     // need to verify mocks
79     private final ExtendedMockitoRule.Builder mUnsafeBuilder =
80             new ExtendedMockitoRule.Builder(mClassUnderTest).dontClearInlineMocks();
81 
82     private final Supplier<StaticMockFixture> mSupplier1 = () -> {
83         return mStaticMockFixture1;
84     };
85     private final Supplier<StaticMockFixture> mSupplier2 = () -> {
86         return mStaticMockFixture2;
87     };
88     private final Supplier<StaticMockFixture> mSupplier3 = () -> {
89         return mStaticMockFixture3;
90     };
91 
92     @Test
testBuilder_constructor_null()93     public void testBuilder_constructor_null() {
94         assertThrows(NullPointerException.class, () -> new ExtendedMockitoRule.Builder(null));
95     }
96 
97     @Test
testBuilder_setStrictness_null()98     public void testBuilder_setStrictness_null() {
99         assertThrows(NullPointerException.class, () -> mBuilder.setStrictness(null));
100     }
101 
102     @Test
testBuilder_mockStatic_null()103     public void testBuilder_mockStatic_null() {
104         assertThrows(NullPointerException.class, () -> mBuilder.mockStatic(null));
105     }
106 
107     @Test
testBuilder_spyStatic_null()108     public void testBuilder_spyStatic_null() {
109         assertThrows(NullPointerException.class, () -> mBuilder.spyStatic(null));
110     }
111 
112     @Test
testBuilder_addStaticMockFixtures_null()113     public void testBuilder_addStaticMockFixtures_null() {
114         assertThrows(NullPointerException.class,
115                 () -> mBuilder.addStaticMockFixtures((Supplier<StaticMockFixture>) null));
116     }
117 
118     @Test
testBuilder_afterSessionFinished_null()119     public void testBuilder_afterSessionFinished_null() {
120         assertThrows(NullPointerException.class, () -> mBuilder.afterSessionFinished(null));
121     }
122 
123     @Test
testBuilder_setMockitoFrameworkForTesting_null()124     public void testBuilder_setMockitoFrameworkForTesting_null() {
125         assertThrows(NullPointerException.class,
126                 () -> mBuilder.setMockitoFrameworkForTesting(null));
127     }
128 
129     @Test
testBuilder_setMockitoSessionForTesting_null()130     public void testBuilder_setMockitoSessionForTesting_null() {
131         assertThrows(NullPointerException.class,
132                 () -> mBuilder.setMockitoSessionForTesting(null));
133     }
134 
135     @Test
testMocksInitialized()136     public void testMocksInitialized() throws Throwable {
137         mBuilder.build().apply(mStatement, mDescription).evaluate();
138 
139         assertWithMessage("@Mock object").that(mClassUnderTest.mMock).isNotNull();
140     }
141 
142     @Test
testMocksNotInitialized()143     public void testMocksNotInitialized() throws Throwable {
144         new ExtendedMockitoRule.Builder().build().apply(mStatement, mDescription).evaluate();
145 
146         assertWithMessage("@Mock object").that(mClassUnderTest.mMock).isNull();
147     }
148 
149     @Test
testStrictness_lenientByDefault()150     public void testStrictness_lenientByDefault() throws Throwable {
151         applyRuleOnTestThatDoesntUseExpectation(/* strictness= */ null);
152     }
153 
154     @Test
testStrictness_lenient()155     public void testStrictness_lenient() throws Throwable {
156         applyRuleOnTestThatDoesntUseExpectation(Strictness.LENIENT);
157     }
158 
159     @Test
testStrictness_warn()160     public void testStrictness_warn() throws Throwable {
161         applyRuleOnTestThatDoesntUseExpectation(Strictness.WARN);
162     }
163 
164     @Test
testStrictness_strict()165     public void testStrictness_strict() throws Throwable {
166         assertThrows(UnnecessaryStubbingException.class,
167                 () -> applyRuleOnTestThatDoesntUseExpectation(Strictness.STRICT_STUBS));
168     }
169 
170     @Test
testMocksStatic()171     public void testMocksStatic() throws Throwable {
172         ExtendedMockitoRule rule = mBuilder.mockStatic(StaticClass.class).build();
173         rule.apply(new Statement() {
174             @Override
175             public void evaluate() throws Throwable {
176                 doReturn("mocko()").when(() -> StaticClass.marco());
177 
178                 assertWithMessage("StaticClass.marco()")
179                         .that(StaticClass.marco()).isEqualTo("mocko()");
180                 assertWithMessage("StaticClass.water()")
181                         .that(StaticClass.water()).isNull(); // not mocked
182             }
183         }, mDescription).evaluate();
184 
185         Set<Class<?>> mockedClasses = rule.getMockedStaticClasses(mDescription);
186         assertWithMessage("rule.getMockedStaticClasses()").that(mockedClasses)
187                 .containsExactly(StaticClass.class);
188         assertThrows(RuntimeException.class,
189                 () -> mockedClasses.add(ExtendedMockitoRuleTest.class));
190     }
191 
192     @Test
testMockStatic_sameClass()193     public void testMockStatic_sameClass() throws Throwable {
194         mBuilder.mockStatic(StaticClass.class);
195 
196         assertThrows(IllegalStateException.class, () -> mBuilder.mockStatic(StaticClass.class));
197     }
198 
199     @Test
testMocksStatic_multipleClasses()200     public void testMocksStatic_multipleClasses() throws Throwable {
201         ExtendedMockitoRule rule = mBuilder.mockStatic(StaticClass.class)
202                 .mockStatic(AnotherStaticClass.class).build();
203         rule.apply(new Statement() {
204             @Override
205             public void evaluate() throws Throwable {
206                 doReturn("mocko()").when(() -> StaticClass.marco());
207                 doReturn("MOCKO()").when(() -> AnotherStaticClass.marco());
208 
209                 assertWithMessage("StaticClass.marco()")
210                         .that(StaticClass.marco()).isEqualTo("mocko()");
211                 assertWithMessage("StaticClass.water()")
212                         .that(StaticClass.water()).isNull(); // not mocked
213 
214                 assertWithMessage("AnotherStaticClass.marco()")
215                         .that(AnotherStaticClass.marco()).isEqualTo("MOCKO()");
216                 assertWithMessage("AnotherStaticClass.water()")
217                         .that(AnotherStaticClass.water()).isNull(); // not mocked
218             }
219         }, mDescription).evaluate();
220 
221         Set<Class<?>> mockedClasses = rule.getMockedStaticClasses(mDescription);
222         assertWithMessage("rule.getMockedStaticClasses()").that(mockedClasses)
223                 .containsExactly(StaticClass.class, AnotherStaticClass.class);
224         assertThrows(RuntimeException.class,
225                 () -> mockedClasses.add(ExtendedMockitoRuleTest.class));
226     }
227 
228     @Test
testMockStatic_ruleAndAnnotation()229     public void testMockStatic_ruleAndAnnotation() throws Throwable {
230         ExtendedMockitoRule rule = mBuilder.mockStatic(StaticClass.class).build();
231 
232         rule.apply(new Statement() {
233             @Override
234             public void evaluate() throws Throwable {
235                 doReturn("mocko()").when(() -> StaticClass.marco());
236                 doReturn("MOCKO()").when(() -> AnotherStaticClass.marco());
237 
238                 assertWithMessage("StaticClass.marco()")
239                         .that(StaticClass.marco()).isEqualTo("mocko()");
240                 assertWithMessage("StaticClass.water()")
241                         .that(StaticClass.water()).isNull(); // not mocked
242 
243                 assertWithMessage("AnotherStaticClass.marco()")
244                         .that(AnotherStaticClass.marco()).isEqualTo("MOCKO()");
245                 assertWithMessage("AnotherStaticClass.water()")
246                         .that(AnotherStaticClass.water()).isNull(); // not mocked
247             }
248         }, newTestMethod(new MockStaticAnnotation(AnotherStaticClass.class))).evaluate();
249     }
250 
251     // Ideally, we should test the annotations indirectly (i.e., by asserting their static classes
252     // are properly mocked, but pragmatically speaking, testing the getSpiedStatic() is enough - and
253     // much simpler
254     @Test
testMockStatic_fromEverywhere()255     public void testMockStatic_fromEverywhere() throws Throwable {
256         ExtendedMockitoRule rule = mBuilder.mockStatic(StaticClass.class).build();
257 
258         Set<Class<?>> mockedClasses = rule.getMockedStaticClasses(newTestMethod(SubClass.class,
259                 new MockStaticAnnotation(AnotherStaticClass.class)));
260 
261         assertWithMessage("rule.getMockedStaticClasses()").that(mockedClasses).containsExactly(
262                 StaticClass.class, AnotherStaticClass.class, StaticClassMockedBySuperClass.class,
263                 AnotherStaticClassMockedBySuperClass.class, StaticClassMockedBySubClass.class,
264                 AnotherStaticClassMockedBySubClass.class);
265         assertThrows(RuntimeException.class,
266                 () -> mockedClasses.add(ExtendedMockitoRuleTest.class));
267     }
268 
269     @Test
testSpyStatic()270     public void testSpyStatic() throws Throwable {
271         ExtendedMockitoRule rule = mBuilder.spyStatic(StaticClass.class).build();
272 
273         rule.apply(new Statement() {
274             @Override
275             public void evaluate() throws Throwable {
276                 doReturn("mocko()").when(() -> StaticClass.marco());
277 
278                 assertWithMessage("StaticClass.marco()")
279                         .that(StaticClass.marco()).isEqualTo("mocko()");
280                 assertWithMessage("StaticClass.water()")
281                         .that(StaticClass.water()).isEqualTo("polo");
282             }
283         }, mDescription).evaluate();
284 
285         Set<Class<?>> spiedClasses = rule.getSpiedStaticClasses(mDescription);
286         assertWithMessage("rule.getSpiedStaticClasses()").that(spiedClasses)
287                 .containsExactly(StaticClass.class);
288         assertThrows(RuntimeException.class, () -> spiedClasses.add(ExtendedMockitoRuleTest.class));
289     }
290 
291     @Test
testSpyStatic_sameClass()292     public void testSpyStatic_sameClass() throws Throwable {
293         mBuilder.spyStatic(StaticClass.class);
294 
295         assertThrows(IllegalStateException.class, () -> mBuilder.spyStatic(StaticClass.class));
296     }
297 
298     @Test
testSpyStatic_multipleClasses()299     public void testSpyStatic_multipleClasses() throws Throwable {
300         ExtendedMockitoRule rule = mBuilder.spyStatic(StaticClass.class)
301                 .spyStatic(AnotherStaticClass.class).build();
302 
303         rule.apply(new Statement() {
304                     @Override
305                     public void evaluate() throws Throwable {
306                         doReturn("mocko()").when(() -> StaticClass.marco());
307                         doReturn("MOCKO()").when(() -> AnotherStaticClass.marco());
308 
309                         assertWithMessage("StaticClass.marco()")
310                                 .that(StaticClass.marco()).isEqualTo("mocko()");
311                         assertWithMessage("StaticClass.water()")
312                                 .that(StaticClass.water()).isEqualTo("polo");
313 
314                         assertWithMessage("AnotherStaticClass.marco()")
315                                 .that(AnotherStaticClass.marco()).isEqualTo("MOCKO()");
316                         assertWithMessage("AnotherStaticClass.water()")
317                                 .that(AnotherStaticClass.water()).isEqualTo("POLO");
318                     }
319                 }, mDescription).evaluate();
320 
321         Set<Class<?>> spiedClasses = rule.getSpiedStaticClasses(mDescription);
322         assertWithMessage("rule.getSpiedStaticClasses()").that(spiedClasses)
323                 .containsExactly(StaticClass.class, AnotherStaticClass.class);
324         assertThrows(RuntimeException.class, () -> spiedClasses.add(ExtendedMockitoRuleTest.class));
325     }
326 
327     @Test
testSpyStatic_ruleAndAnnotation()328     public void testSpyStatic_ruleAndAnnotation() throws Throwable {
329         ExtendedMockitoRule rule = mBuilder.spyStatic(StaticClass.class).build();
330         rule.apply(new Statement() {
331             @Override
332             public void evaluate() throws Throwable {
333                 doReturn("mocko()").when(() -> StaticClass.marco());
334                 doReturn("MOCKO()").when(() -> AnotherStaticClass.marco());
335 
336                 assertWithMessage("StaticClass.marco()")
337                         .that(StaticClass.marco()).isEqualTo("mocko()");
338                 assertWithMessage("StaticClass.water()")
339                         .that(StaticClass.water()).isEqualTo("polo");
340 
341                 assertWithMessage("AnotherStaticClass.marco()")
342                         .that(AnotherStaticClass.marco()).isEqualTo("MOCKO()");
343                 assertWithMessage("AnotherStaticClass.water()")
344                         .that(AnotherStaticClass.water()).isEqualTo("POLO");
345             }
346         }, newTestMethod(new SpyStaticAnnotation(AnotherStaticClass.class))).evaluate();
347     }
348 
349     // Ideally, we should test the annotations indirectly (i.e., by asserting their static classes
350     // are properly spied, but pragmatically speaking, testing the getSpiedStatic() is enough - and
351     // much simpler
352     @Test
testSpyStatic_fromEverywhere()353     public void testSpyStatic_fromEverywhere() throws Throwable {
354         ExtendedMockitoRule rule = mBuilder.spyStatic(StaticClass.class).build();
355 
356         Set<Class<?>> spiedClasses = rule.getSpiedStaticClasses(newTestMethod(SubClass.class,
357                 new SpyStaticAnnotation(AnotherStaticClass.class)));
358 
359         assertWithMessage("rule.getSpiedStaticClasses()").that(spiedClasses).containsExactly(
360                 StaticClass.class, AnotherStaticClass.class, StaticClassSpiedBySuperClass.class,
361                 AnotherStaticClassSpiedBySuperClass.class, StaticClassSpiedBySubClass.class,
362                 AnotherStaticClassSpiedBySubClass.class);
363         assertThrows(RuntimeException.class, () -> spiedClasses.add(ExtendedMockitoRuleTest.class));
364     }
365 
366     @Test
testMockAndSpyStatic()367     public void testMockAndSpyStatic() throws Throwable {
368         ExtendedMockitoRule rule = mBuilder.mockStatic(StaticClass.class)
369                 .spyStatic(AnotherStaticClass.class).build();
370 
371         rule.apply(new Statement() {
372                     @Override
373                     public void evaluate() throws Throwable {
374                         doReturn("mocko()").when(() -> StaticClass.marco());
375                         doReturn("MOCKO()").when(() -> AnotherStaticClass.marco());
376 
377                         assertWithMessage("StaticClass.marco()")
378                                 .that(StaticClass.marco()).isEqualTo("mocko()");
379                         assertWithMessage("StaticClass.water()")
380                                 .that(StaticClass.water()).isNull(); // not mocked
381 
382                         assertWithMessage("AnotherStaticClass.marco()")
383                                 .that(AnotherStaticClass.marco()).isEqualTo("MOCKO()");
384                         assertWithMessage("AnotherStaticClass.water()")
385                                 .that(AnotherStaticClass.water()).isEqualTo("POLO");
386                     }
387                 }, mDescription).evaluate();
388 
389         Set<Class<?>> spiedStaticClasses = rule.getSpiedStaticClasses(mDescription);
390         assertWithMessage("rule.getSpiedStaticClasses()").that(spiedStaticClasses)
391                 .containsExactly(AnotherStaticClass.class);
392         assertThrows(RuntimeException.class,
393                 () -> spiedStaticClasses.add(ExtendedMockitoRuleTest.class));
394 
395         Set<Class<?>> mockedStaticClasses = rule.getMockedStaticClasses(mDescription);
396         assertWithMessage("rule.getMockedStaticClasses()").that(mockedStaticClasses)
397                 .containsExactly(StaticClass.class);
398         assertThrows(RuntimeException.class,
399                 () -> mockedStaticClasses.add(ExtendedMockitoRuleTest.class));
400     }
401 
402     @Test
testMockAndSpyStatic_sameClass()403     public void testMockAndSpyStatic_sameClass() throws Throwable {
404         mBuilder.mockStatic(StaticClass.class);
405 
406         assertThrows(IllegalStateException.class, () -> mBuilder.spyStatic(StaticClass.class));
407     }
408 
409     @Test
testSpyAndMockStatic_sameClass()410     public void testSpyAndMockStatic_sameClass() throws Throwable {
411         mBuilder.spyStatic(StaticClass.class);
412 
413         assertThrows(IllegalStateException.class, () -> mBuilder.mockStatic(StaticClass.class));
414     }
415 
416     @Test
testAddStaticMockFixtures_once()417     public void testAddStaticMockFixtures_once() throws Throwable {
418         InOrder inOrder = inOrder(mStaticMockFixture1, mStaticMockFixture2);
419 
420         mUnsafeBuilder
421                 .addStaticMockFixtures(mSupplier1, mSupplier2)
422                 .build().apply(mStatement, mDescription).evaluate();
423 
424         inOrder.verify(mStaticMockFixture1).setUpMockedClasses(any());
425         inOrder.verify(mStaticMockFixture2).setUpMockedClasses(any());
426 
427         inOrder.verify(mStaticMockFixture1).setUpMockBehaviors();
428         inOrder.verify(mStaticMockFixture2).setUpMockBehaviors();
429 
430         inOrder.verify(mStaticMockFixture2).tearDown();
431         inOrder.verify(mStaticMockFixture1).tearDown();
432     }
433 
434     @Test
testAddStaticMockFixtures_twice()435     public void testAddStaticMockFixtures_twice() throws Throwable {
436         InOrder inOrder = inOrder(mStaticMockFixture1, mStaticMockFixture2, mStaticMockFixture3,
437                 mStaticMockFixture3);
438 
439         mUnsafeBuilder
440                 .addStaticMockFixtures(mSupplier1, mSupplier2)
441                 .addStaticMockFixtures(mSupplier3)
442                 .build().apply(mStatement, mDescription).evaluate();
443 
444         inOrder.verify(mStaticMockFixture1).setUpMockedClasses(any());
445         inOrder.verify(mStaticMockFixture2).setUpMockedClasses(any());
446         inOrder.verify(mStaticMockFixture3).setUpMockedClasses(any());
447 
448         inOrder.verify(mStaticMockFixture1).setUpMockBehaviors();
449         inOrder.verify(mStaticMockFixture2).setUpMockBehaviors();
450         inOrder.verify(mStaticMockFixture3).setUpMockBehaviors();
451 
452         inOrder.verify(mStaticMockFixture3).tearDown();
453         inOrder.verify(mStaticMockFixture2).tearDown();
454         inOrder.verify(mStaticMockFixture1).tearDown();
455     }
456 
457     @Test
testMockAndSpyStaticAndAddStaticMockFixtures()458     public void testMockAndSpyStaticAndAddStaticMockFixtures() throws Throwable {
459         InOrder inOrder = inOrder(mStaticMockFixture1, mStaticMockFixture2, mStaticMockFixture3,
460                 mStaticMockFixture3);
461 
462         mUnsafeBuilder
463                 .mockStatic(StaticClass.class)
464                 .spyStatic(AnotherStaticClass.class)
465                 .addStaticMockFixtures(mSupplier1, mSupplier2)
466                 .addStaticMockFixtures(mSupplier3)
467                 .build()
468                 .apply(new Statement() {
469                     @Override
470                     public void evaluate() throws Throwable {
471                         doReturn("mocko()").when(() -> StaticClass.marco());
472                         doReturn("MOCKO()").when(() -> AnotherStaticClass.marco());
473 
474                         assertWithMessage("StaticClass.marco()")
475                                 .that(StaticClass.marco()).isEqualTo("mocko()");
476                         assertWithMessage("StaticClass.water()")
477                                 .that(StaticClass.water()).isNull(); // not mocked
478 
479                         assertWithMessage("AnotherStaticClass.marco()")
480                                 .that(AnotherStaticClass.marco()).isEqualTo("MOCKO()");
481                         assertWithMessage("AnotherStaticClass.water()")
482                                 .that(AnotherStaticClass.water()).isEqualTo("POLO");
483                     }
484                 }, mDescription).evaluate();
485 
486         inOrder.verify(mStaticMockFixture1).setUpMockedClasses(any());
487         inOrder.verify(mStaticMockFixture2).setUpMockedClasses(any());
488         inOrder.verify(mStaticMockFixture3).setUpMockedClasses(any());
489 
490         inOrder.verify(mStaticMockFixture1).setUpMockBehaviors();
491         inOrder.verify(mStaticMockFixture2).setUpMockBehaviors();
492         inOrder.verify(mStaticMockFixture3).setUpMockBehaviors();
493 
494         inOrder.verify(mStaticMockFixture3).tearDown();
495         inOrder.verify(mStaticMockFixture2).tearDown();
496         inOrder.verify(mStaticMockFixture1).tearDown();
497     }
498 
499     @Test
testAfterSessionFinished()500     public void testAfterSessionFinished() throws Throwable {
501         mUnsafeBuilder.afterSessionFinished(mRunnable).build().apply(mStatement, mDescription)
502                 .evaluate();
503 
504         verify(mRunnable).run();
505     }
506 
507     @Test
testAfterSessionFinished_whenSessionFailsToFinish()508     public void testAfterSessionFinished_whenSessionFailsToFinish() throws Throwable {
509         MockitoSessionThatFailsToFinish mockitoSession = new MockitoSessionThatFailsToFinish();
510 
511         Exception thrown = assertThrows(Exception.class,
512                 () -> mUnsafeBuilder.afterSessionFinished(mRunnable)
513                         .setMockitoSessionForTesting(mockitoSession)
514                         .build().apply(mStatement, mDescription).evaluate());
515 
516         assertWithMessage("exception").that(thrown).isSameInstanceAs(mockitoSession.e);
517         verify(mRunnable).run();
518     }
519 
520     @Test
testMockitoFrameworkCleared()521     public void testMockitoFrameworkCleared() throws Throwable {
522         MyMockitoFramework mockitoFramework = new MyMockitoFramework();
523 
524         mBuilder.setMockitoFrameworkForTesting(mockitoFramework).build()
525                 .apply(mStatement, mDescription)
526                 .evaluate();
527 
528         assertWithMessage("mockito framework cleared").that(mockitoFramework.called).isTrue();
529     }
530 
531     @Test
testMockitoFrameworkNotCleared_whenSetOnBuilder()532     public void testMockitoFrameworkNotCleared_whenSetOnBuilder() throws Throwable {
533         MyMockitoFramework mockitoFramework = new MyMockitoFramework();
534 
535         mBuilder.dontClearInlineMocks().setMockitoFrameworkForTesting(mockitoFramework).build()
536                 .apply(mStatement, mDescription)
537                 .evaluate();
538 
539         assertWithMessage("mockito framework cleared").that(mockitoFramework.called).isFalse();
540     }
541 
542     @Test
testMockitoFrameworkCleared_whenTestFails()543     public void testMockitoFrameworkCleared_whenTestFails() throws Throwable {
544         MyMockitoFramework mockitoFramework = new MyMockitoFramework();
545         Exception exception = new Exception("D'OH!");
546 
547         Exception thrown = assertThrows(Exception.class,
548                 () -> mBuilder.setMockitoFrameworkForTesting(mockitoFramework).build()
549                         .apply(new Statement() {
550                             @Override
551                             public void evaluate() throws Throwable {
552                                 throw exception;
553                             }
554                         }, mDescription).evaluate());
555 
556         assertWithMessage("exception").that(thrown).isSameInstanceAs(exception);
557         assertWithMessage("mockito framework cleared").that(mockitoFramework.called).isTrue();
558     }
559 
560     @Test
testMockitoFrameworkCleared_whenAfterSessionFinished()561     public void testMockitoFrameworkCleared_whenAfterSessionFinished() throws Throwable {
562         MyMockitoFramework mockitoFramework = new MyMockitoFramework();
563         RuntimeException exception = new RuntimeException("D'OH!");
564 
565         Exception thrown = assertThrows(Exception.class,
566                 () -> mBuilder.setMockitoFrameworkForTesting(mockitoFramework)
567                         .afterSessionFinished(() -> {
568                             throw exception;
569                         }).build().apply(mStatement, mDescription).evaluate());
570 
571         assertWithMessage("exception").that(thrown).isSameInstanceAs(exception);
572         assertWithMessage("mockito framework cleared").that(mockitoFramework.called).isTrue();
573     }
574 
575     @Test
testMockitoFrameworkCleared_whenStaticMockFixturesFailed()576     public void testMockitoFrameworkCleared_whenStaticMockFixturesFailed() throws Throwable {
577         MyMockitoFramework mockitoFramework = new MyMockitoFramework();
578         RuntimeException exception = new RuntimeException("D'OH!");
579         doThrow(exception).when(mStaticMockFixture1).tearDown();
580 
581         Exception thrown = assertThrows(Exception.class,
582                 () -> mBuilder.setMockitoFrameworkForTesting(mockitoFramework)
583                         .addStaticMockFixtures(mSupplier1).build().apply(mStatement, mDescription)
584                         .evaluate());
585 
586         assertWithMessage("exception").that(thrown).isSameInstanceAs(exception);
587         assertWithMessage("mockito framework cleared").that(mockitoFramework.called).isTrue();
588     }
589 
590     @Test
testMockitoFrameworkCleared_whenSessionFailsToFinish()591     public void testMockitoFrameworkCleared_whenSessionFailsToFinish() throws Throwable {
592         MyMockitoFramework mockitoFramework = new MyMockitoFramework();
593         MockitoSessionThatFailsToFinish mockitoSession = new MockitoSessionThatFailsToFinish();
594 
595         Exception thrown = assertThrows(Exception.class,
596                 () -> mBuilder.setMockitoFrameworkForTesting(mockitoFramework)
597                         .setMockitoSessionForTesting(mockitoSession).build()
598                         .apply(mStatement, mDescription).evaluate());
599 
600         assertWithMessage("exception").that(thrown).isSameInstanceAs(mockitoSession.e);
601         assertWithMessage("mockito framework cleared").that(mockitoFramework.called).isTrue();
602     }
603 
604     @Test
testMockitoSessionFinished_whenStaticMockFixturesSetupFailed()605     public void testMockitoSessionFinished_whenStaticMockFixturesSetupFailed() throws Throwable {
606         RuntimeException exception = new RuntimeException("D'OH!");
607         doThrow(exception).when(mStaticMockFixture1).setUpMockBehaviors();
608 
609         assertThrows(Exception.class,
610                 () -> mBuilder.addStaticMockFixtures(mSupplier1)
611                         .build().apply(mStatement, mDescription).evaluate());
612 
613         // Assert that the previous session was closed.
614         Mockito.mockitoSession().startMocking().finishMocking();
615     }
616 
617     @Test
testGetClearInlineMethodsAtTheEnd()618     public void testGetClearInlineMethodsAtTheEnd() throws Throwable {
619         assertWithMessage("getClearInlineMethodsAtTheEnd() by default")
620                 .that(mBuilder.build().getClearInlineMethodsAtTheEnd(mDescription)).isTrue();
621         assertWithMessage("getClearInlineMethodsAtTheEnd() when built with dontClearInlineMocks()")
622                 .that(mBuilder.dontClearInlineMocks().build()
623                         .getClearInlineMethodsAtTheEnd(mDescription))
624                 .isFalse();
625     }
626 
applyRuleOnTestThatDoesntUseExpectation(@ullable Strictness strictness)627     private void applyRuleOnTestThatDoesntUseExpectation(@Nullable Strictness strictness)
628             throws Throwable {
629         Log.d(TAG, "applyRuleOnTestThatDoesntUseExpectation(): strictness= " + strictness);
630         if (strictness != null) {
631             mBuilder.setStrictness(strictness);
632         }
633         mBuilder.build().apply(new Statement() {
634             @Override
635             public void evaluate() throws Throwable {
636                 when(mClassUnderTest.mMock.getMeaningOfLife()).thenReturn(42);
637             }
638         }, mDescription).evaluate();
639     }
640 
newTestMethod(Annotation... annotations)641     private static Description newTestMethod(Annotation... annotations) {
642         return newTestMethod(ClassUnderTest.class, annotations);
643     }
644 
newTestMethod(Class<?> testClass, Annotation... annotations)645     private static Description newTestMethod(Class<?> testClass, Annotation... annotations) {
646         return Description.createTestDescription(testClass, TEST_METHOD_BEING_EXECUTED,
647                 annotations);
648     }
649 
650     private static final class ClassUnderTest {
651         @Mock
652         public DumbObject mMock;
653     }
654 
655     private static final class StaticClass {
656 
marco()657         public static String marco() {
658             Log.d(TAG, "StaticClass.marco() called");
659             return "polo";
660         }
661 
water()662         public static String water() {
663             Log.d(TAG, "StaticClass.water() called");
664             return "polo";
665         }
666     }
667 
668     private static final class AnotherStaticClass {
669 
marco()670         public static String marco() {
671             Log.d(TAG, "AnotherStaticClass.marco() called");
672             return "POLO";
673         }
674 
water()675         public static String water() {
676             Log.d(TAG, "AnotherStaticClass.water() called");
677             return "POLO";
678         }
679     }
680 
681     private static class DumbObject {
682 
getMeaningOfLife()683         public int getMeaningOfLife() {
684             Log.d(TAG, "getMeaningOfLife() called");
685             throw new UnsupportedOperationException("Ask Bard");
686         }
687     }
688 
689     // Used on tests that check if the clearInlineMocks() is called - such tests cannot mock a
690     // MockitoFramework because of that
691     private static final class MyMockitoFramework implements MockitoFramework {
692 
693         private static int sCounter;
694 
695         private final int mId = ++sCounter;
696         public boolean called;
697 
698         @Override
removeListener(MockitoListener arg0)699         public MockitoFramework removeListener(MockitoListener arg0) {
700             return null;
701         }
702 
703         @Override
getPlugins()704         public MockitoPlugins getPlugins() {
705             return null;
706         }
707 
708         @Override
getInvocationFactory()709         public InvocationFactory getInvocationFactory() {
710             return null;
711         }
712 
713         @Override
clearInlineMocks()714         public void clearInlineMocks() {
715             called = true;
716         }
717 
718         @Override
clearInlineMock(Object arg0)719         public void clearInlineMock(Object arg0) {
720         }
721 
722         @Override
addListener(MockitoListener arg0)723         public MockitoFramework addListener(MockitoListener arg0) {
724             return null;
725         }
726 
727         @Override
toString()728         public String toString() {
729             return "MyMockitoFramework-" + mId;
730         }
731     };
732 
733     // Used on tests that check if the clearInlineMocks() is called - such tests cannot mock a
734     // MockitoSession because of that
735     private static final class MockitoSessionThatFailsToFinish implements MockitoSession {
736         public final RuntimeException e = new RuntimeException("D'OH!");
737 
738         @Override
setStrictness(Strictness strictness)739         public void setStrictness(Strictness strictness) {
740         }
741 
742         @Override
finishMocking()743         public void finishMocking() {
744             throw e;
745         }
746 
747         @Override
finishMocking(Throwable failure)748         public void finishMocking(Throwable failure) {
749             throw e;
750         }
751     }
752 
753     private abstract static class ClassAnnotation<A extends Annotation> implements Annotation {
754         private Class<A> mAnnotationType;
755         private Class<?> mClass;
756 
ClassAnnotation(Class<A> annotationType, Class<?> clazz)757         private ClassAnnotation(Class<A> annotationType, Class<?> clazz) {
758             mAnnotationType = annotationType;
759             mClass = clazz;
760         }
761 
762         @Override
annotationType()763         public final Class<A> annotationType() {
764             return mAnnotationType;
765         }
766 
value()767         public final Class<?> value() {
768             return mClass;
769         }
770 
771         @Override
hashCode()772         public int hashCode() {
773             return Objects.hash(mAnnotationType, mClass);
774         }
775 
776         @Override
equals(Object obj)777         public boolean equals(Object obj) {
778             if (this == obj) {
779                 return true;
780             }
781             if (obj == null) {
782                 return false;
783             }
784             if (getClass() != obj.getClass()) {
785                 return false;
786             }
787             ClassAnnotation other = (ClassAnnotation) obj;
788             return Objects.equals(mAnnotationType, other.mAnnotationType)
789                     && Objects.equals(mClass, other.mClass);
790         }
791 
792         @Override
toString()793         public String toString() {
794             return getClass().getSimpleName() + "[" + mClass.getSimpleName() + "]";
795         }
796     }
797 
798     private static final class SpyStaticAnnotation extends ClassAnnotation<SpyStatic>
799             implements SpyStatic {
800 
SpyStaticAnnotation(Class<?> clazz)801         private SpyStaticAnnotation(Class<?> clazz) {
802             super(SpyStatic.class, clazz);
803         }
804     }
805 
806     private static final class MockStaticAnnotation extends ClassAnnotation<MockStatic>
807             implements MockStatic {
808 
MockStaticAnnotation(Class<?> clazz)809         private MockStaticAnnotation(Class<?> clazz) {
810             super(MockStatic.class, clazz);
811         }
812     }
813 
814     private static final class StaticClassMockedBySuperClass {
815     }
816 
817     private static final class AnotherStaticClassMockedBySuperClass {
818     }
819     private static final class StaticClassSpiedBySuperClass {
820     }
821 
822     private static final class AnotherStaticClassSpiedBySuperClass {
823     }
824 
825     @SpyStatic(StaticClassSpiedBySuperClass.class)
826     @SpyStatic(AnotherStaticClassSpiedBySuperClass.class)
827     @MockStatic(StaticClassMockedBySuperClass.class)
828     @MockStatic(AnotherStaticClassMockedBySuperClass.class)
829     private static class SuperClass {
830 
831     }
832 
833     private static final class StaticClassMockedBySubClass {
834     }
835 
836     private static final class AnotherStaticClassMockedBySubClass {
837     }
838 
839     private static final class StaticClassSpiedBySubClass {
840     }
841 
842     private static final class AnotherStaticClassSpiedBySubClass {
843     }
844 
845     @SpyStatic(StaticClassSpiedBySubClass.class)
846     @SpyStatic(AnotherStaticClassSpiedBySubClass.class)
847     @MockStatic(StaticClassMockedBySubClass.class)
848     @MockStatic(AnotherStaticClassMockedBySubClass.class)
849     private static final class SubClass extends SuperClass{
850     }
851 }
852