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