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