1 /* 2 * Copyright (c) 2007 Mockito contributors 3 * This program is made available under the terms of the MIT License. 4 */ 5 package org.mockito.internal; 6 7 import static org.mockito.internal.exceptions.Reporter.missingMethodInvocation; 8 import static org.mockito.internal.exceptions.Reporter.mocksHaveToBePassedToVerifyNoMoreInteractions; 9 import static org.mockito.internal.exceptions.Reporter.mocksHaveToBePassedWhenCreatingInOrder; 10 import static org.mockito.internal.exceptions.Reporter.notAMockPassedToVerify; 11 import static org.mockito.internal.exceptions.Reporter.notAMockPassedToVerifyNoMoreInteractions; 12 import static org.mockito.internal.exceptions.Reporter.notAMockPassedWhenCreatingInOrder; 13 import static org.mockito.internal.exceptions.Reporter.nullPassedToVerify; 14 import static org.mockito.internal.exceptions.Reporter.nullPassedToVerifyNoMoreInteractions; 15 import static org.mockito.internal.exceptions.Reporter.nullPassedWhenCreatingInOrder; 16 import static org.mockito.internal.exceptions.Reporter.stubPassedToVerify; 17 import static org.mockito.internal.progress.ThreadSafeMockingProgress.mockingProgress; 18 import static org.mockito.internal.util.MockUtil.createConstructionMock; 19 import static org.mockito.internal.util.MockUtil.createMock; 20 import static org.mockito.internal.util.MockUtil.createStaticMock; 21 import static org.mockito.internal.util.MockUtil.getInvocationContainer; 22 import static org.mockito.internal.util.MockUtil.getMockHandler; 23 import static org.mockito.internal.util.MockUtil.isMock; 24 import static org.mockito.internal.util.MockUtil.resetMock; 25 import static org.mockito.internal.util.MockUtil.typeMockabilityOf; 26 import static org.mockito.internal.verification.VerificationModeFactory.noInteractions; 27 import static org.mockito.internal.verification.VerificationModeFactory.noMoreInteractions; 28 29 import java.util.Arrays; 30 import java.util.Collections; 31 import java.util.HashSet; 32 import java.util.List; 33 import java.util.Set; 34 35 import org.mockito.InOrder; 36 import org.mockito.MockSettings; 37 import org.mockito.MockedConstruction; 38 import org.mockito.MockedStatic; 39 import org.mockito.MockingDetails; 40 import org.mockito.exceptions.misusing.DoNotMockException; 41 import org.mockito.exceptions.misusing.NotAMockException; 42 import org.mockito.internal.configuration.plugins.Plugins; 43 import org.mockito.internal.creation.MockSettingsImpl; 44 import org.mockito.internal.invocation.finder.VerifiableInvocationsFinder; 45 import org.mockito.internal.listeners.VerificationStartedNotifier; 46 import org.mockito.internal.progress.MockingProgress; 47 import org.mockito.internal.stubbing.DefaultLenientStubber; 48 import org.mockito.internal.stubbing.InvocationContainerImpl; 49 import org.mockito.internal.stubbing.OngoingStubbingImpl; 50 import org.mockito.internal.stubbing.StubberImpl; 51 import org.mockito.internal.util.DefaultMockingDetails; 52 import org.mockito.internal.util.MockUtil; 53 import org.mockito.internal.verification.MockAwareVerificationMode; 54 import org.mockito.internal.verification.VerificationDataImpl; 55 import org.mockito.internal.verification.VerificationModeFactory; 56 import org.mockito.internal.verification.api.InOrderContext; 57 import org.mockito.internal.verification.api.VerificationDataInOrder; 58 import org.mockito.internal.verification.api.VerificationDataInOrderImpl; 59 import org.mockito.invocation.Invocation; 60 import org.mockito.invocation.MockHandler; 61 import org.mockito.mock.MockCreationSettings; 62 import org.mockito.plugins.DoNotMockEnforcer; 63 import org.mockito.plugins.MockMaker; 64 import org.mockito.quality.Strictness; 65 import org.mockito.stubbing.LenientStubber; 66 import org.mockito.stubbing.OngoingStubbing; 67 import org.mockito.stubbing.Stubber; 68 import org.mockito.verification.VerificationMode; 69 70 import java.util.Arrays; 71 import java.util.List; 72 import java.util.function.Function; 73 74 @SuppressWarnings("unchecked") 75 public class MockitoCore { 76 77 private static final DoNotMockEnforcer DO_NOT_MOCK_ENFORCER = Plugins.getDoNotMockEnforcer(); 78 private static final Set<Class<?>> MOCKABLE_CLASSES = 79 Collections.synchronizedSet(new HashSet<>()); 80 isTypeMockable(Class<?> typeToMock)81 public boolean isTypeMockable(Class<?> typeToMock) { 82 return typeMockabilityOf(typeToMock).mockable(); 83 } 84 mock(Class<T> typeToMock, MockSettings settings)85 public <T> T mock(Class<T> typeToMock, MockSettings settings) { 86 if (!(settings instanceof MockSettingsImpl)) { 87 throw new IllegalArgumentException( 88 "Unexpected implementation of '" 89 + settings.getClass().getCanonicalName() 90 + "'\n" 91 + "At the moment, you cannot provide your own implementations of that class."); 92 } 93 MockSettingsImpl impl = (MockSettingsImpl) settings; 94 MockCreationSettings<T> creationSettings = impl.build(typeToMock); 95 checkDoNotMockAnnotation(creationSettings.getTypeToMock(), creationSettings); 96 T mock = createMock(creationSettings); 97 mockingProgress().mockingStarted(mock, creationSettings); 98 return mock; 99 } 100 checkDoNotMockAnnotation( Class<?> typeToMock, MockCreationSettings<?> creationSettings)101 private void checkDoNotMockAnnotation( 102 Class<?> typeToMock, MockCreationSettings<?> creationSettings) { 103 checkDoNotMockAnnotationForType(typeToMock); 104 for (Class<?> aClass : creationSettings.getExtraInterfaces()) { 105 checkDoNotMockAnnotationForType(aClass); 106 } 107 } 108 checkDoNotMockAnnotationForType(Class<?> type)109 private static void checkDoNotMockAnnotationForType(Class<?> type) { 110 // Object and interfaces do not have a super class 111 if (type == null) { 112 return; 113 } 114 115 if (MOCKABLE_CLASSES.contains(type)) { 116 return; 117 } 118 119 String warning = DO_NOT_MOCK_ENFORCER.checkTypeForDoNotMockViolation(type); 120 if (warning != null) { 121 throw new DoNotMockException(warning); 122 } 123 124 checkDoNotMockAnnotationForType(type.getSuperclass()); 125 for (Class<?> aClass : type.getInterfaces()) { 126 checkDoNotMockAnnotationForType(aClass); 127 } 128 129 MOCKABLE_CLASSES.add(type); 130 } 131 mockStatic(Class<T> classToMock, MockSettings settings)132 public <T> MockedStatic<T> mockStatic(Class<T> classToMock, MockSettings settings) { 133 if (!MockSettingsImpl.class.isInstance(settings)) { 134 throw new IllegalArgumentException( 135 "Unexpected implementation of '" 136 + settings.getClass().getCanonicalName() 137 + "'\n" 138 + "At the moment, you cannot provide your own implementations of that class."); 139 } 140 MockSettingsImpl impl = MockSettingsImpl.class.cast(settings); 141 MockCreationSettings<T> creationSettings = impl.buildStatic(classToMock); 142 MockMaker.StaticMockControl<T> control = createStaticMock(classToMock, creationSettings); 143 control.enable(); 144 mockingProgress().mockingStarted(classToMock, creationSettings); 145 return new MockedStaticImpl<>(control); 146 } 147 mockConstruction( Class<T> typeToMock, Function<MockedConstruction.Context, ? extends MockSettings> settingsFactory, MockedConstruction.MockInitializer<T> mockInitializer)148 public <T> MockedConstruction<T> mockConstruction( 149 Class<T> typeToMock, 150 Function<MockedConstruction.Context, ? extends MockSettings> settingsFactory, 151 MockedConstruction.MockInitializer<T> mockInitializer) { 152 Function<MockedConstruction.Context, MockCreationSettings<T>> creationSettings = 153 context -> { 154 MockSettings value = settingsFactory.apply(context); 155 if (!MockSettingsImpl.class.isInstance(value)) { 156 throw new IllegalArgumentException( 157 "Unexpected implementation of '" 158 + value.getClass().getCanonicalName() 159 + "'\n" 160 + "At the moment, you cannot provide your own implementations of that class."); 161 } 162 MockSettingsImpl impl = MockSettingsImpl.class.cast(value); 163 return impl.build(typeToMock); 164 }; 165 MockMaker.ConstructionMockControl<T> control = 166 createConstructionMock(typeToMock, creationSettings, mockInitializer); 167 control.enable(); 168 return new MockedConstructionImpl<>(control); 169 } 170 when(T methodCall)171 public <T> OngoingStubbing<T> when(T methodCall) { 172 MockingProgress mockingProgress = mockingProgress(); 173 mockingProgress.stubbingStarted(); 174 @SuppressWarnings("unchecked") 175 OngoingStubbing<T> stubbing = (OngoingStubbing<T>) mockingProgress.pullOngoingStubbing(); 176 if (stubbing == null) { 177 mockingProgress.reset(); 178 throw missingMethodInvocation(); 179 } 180 return stubbing; 181 } 182 verify(T mock, VerificationMode mode)183 public <T> T verify(T mock, VerificationMode mode) { 184 if (mock == null) { 185 throw nullPassedToVerify(); 186 } 187 MockingDetails mockingDetails = mockingDetails(mock); 188 if (!mockingDetails.isMock()) { 189 throw notAMockPassedToVerify(mock.getClass()); 190 } 191 assertNotStubOnlyMock(mock); 192 MockHandler handler = mockingDetails.getMockHandler(); 193 mock = 194 (T) 195 VerificationStartedNotifier.notifyVerificationStarted( 196 handler.getMockSettings().getVerificationStartedListeners(), 197 mockingDetails); 198 199 MockingProgress mockingProgress = mockingProgress(); 200 VerificationMode actualMode = mockingProgress.maybeVerifyLazily(mode); 201 mockingProgress.verificationStarted( 202 new MockAwareVerificationMode( 203 mock, actualMode, mockingProgress.verificationListeners())); 204 return mock; 205 } 206 reset(T... mocks)207 public <T> void reset(T... mocks) { 208 MockingProgress mockingProgress = mockingProgress(); 209 mockingProgress.validateState(); 210 mockingProgress.reset(); 211 mockingProgress.resetOngoingStubbing(); 212 213 for (T m : mocks) { 214 resetMock(m); 215 } 216 } 217 clearInvocations(T... mocks)218 public <T> void clearInvocations(T... mocks) { 219 MockingProgress mockingProgress = mockingProgress(); 220 mockingProgress.validateState(); 221 mockingProgress.reset(); 222 mockingProgress.resetOngoingStubbing(); 223 224 for (T m : mocks) { 225 getInvocationContainer(m).clearInvocations(); 226 } 227 } 228 verifyNoMoreInteractions(Object... mocks)229 public void verifyNoMoreInteractions(Object... mocks) { 230 assertMocksNotEmpty(mocks); 231 mockingProgress().validateState(); 232 for (Object mock : mocks) { 233 try { 234 if (mock == null) { 235 throw nullPassedToVerifyNoMoreInteractions(); 236 } 237 InvocationContainerImpl invocations = getInvocationContainer(mock); 238 assertNotStubOnlyMock(mock); 239 VerificationDataImpl data = new VerificationDataImpl(invocations, null); 240 noMoreInteractions().verify(data); 241 } catch (NotAMockException e) { 242 throw notAMockPassedToVerifyNoMoreInteractions(); 243 } 244 } 245 } 246 verifyNoInteractions(Object... mocks)247 public void verifyNoInteractions(Object... mocks) { 248 assertMocksNotEmpty(mocks); 249 mockingProgress().validateState(); 250 for (Object mock : mocks) { 251 try { 252 if (mock == null) { 253 throw nullPassedToVerifyNoMoreInteractions(); 254 } 255 InvocationContainerImpl invocations = getInvocationContainer(mock); 256 assertNotStubOnlyMock(mock); 257 VerificationDataImpl data = new VerificationDataImpl(invocations, null); 258 noInteractions().verify(data); 259 } catch (NotAMockException e) { 260 throw notAMockPassedToVerifyNoMoreInteractions(); 261 } 262 } 263 } 264 verifyNoMoreInteractionsInOrder(List<Object> mocks, InOrderContext inOrderContext)265 public void verifyNoMoreInteractionsInOrder(List<Object> mocks, InOrderContext inOrderContext) { 266 mockingProgress().validateState(); 267 VerificationDataInOrder data = 268 new VerificationDataInOrderImpl( 269 inOrderContext, VerifiableInvocationsFinder.find(mocks), null); 270 VerificationModeFactory.noMoreInteractions().verifyInOrder(data); 271 } 272 assertMocksNotEmpty(Object[] mocks)273 private void assertMocksNotEmpty(Object[] mocks) { 274 if (mocks == null || mocks.length == 0) { 275 throw mocksHaveToBePassedToVerifyNoMoreInteractions(); 276 } 277 } 278 assertNotStubOnlyMock(Object mock)279 private void assertNotStubOnlyMock(Object mock) { 280 if (getMockHandler(mock).getMockSettings().isStubOnly()) { 281 throw stubPassedToVerify(mock); 282 } 283 } 284 inOrder(Object... mocks)285 public InOrder inOrder(Object... mocks) { 286 if (mocks == null || mocks.length == 0) { 287 throw mocksHaveToBePassedWhenCreatingInOrder(); 288 } 289 for (Object mock : mocks) { 290 if (mock == null) { 291 throw nullPassedWhenCreatingInOrder(); 292 } 293 if (!isMock(mock)) { 294 throw notAMockPassedWhenCreatingInOrder(); 295 } 296 assertNotStubOnlyMock(mock); 297 } 298 return new InOrderImpl(Arrays.asList(mocks)); 299 } 300 stubber()301 public Stubber stubber() { 302 return stubber(null); 303 } 304 stubber(Strictness strictness)305 public Stubber stubber(Strictness strictness) { 306 MockingProgress mockingProgress = mockingProgress(); 307 mockingProgress.stubbingStarted(); 308 mockingProgress.resetOngoingStubbing(); 309 return new StubberImpl(strictness); 310 } 311 validateMockitoUsage()312 public void validateMockitoUsage() { 313 mockingProgress().validateState(); 314 } 315 316 /** 317 * For testing purposes only. Is not the part of main API. 318 * 319 * @return last invocation 320 */ getLastInvocation()321 public Invocation getLastInvocation() { 322 OngoingStubbingImpl ongoingStubbing = 323 ((OngoingStubbingImpl) mockingProgress().pullOngoingStubbing()); 324 List<Invocation> allInvocations = ongoingStubbing.getRegisteredInvocations(); 325 return allInvocations.get(allInvocations.size() - 1); 326 } 327 ignoreStubs(Object... mocks)328 public Object[] ignoreStubs(Object... mocks) { 329 for (Object m : mocks) { 330 InvocationContainerImpl container = getInvocationContainer(m); 331 List<Invocation> ins = container.getInvocations(); 332 for (Invocation in : ins) { 333 if (in.stubInfo() != null) { 334 in.ignoreForVerification(); 335 } 336 } 337 } 338 return mocks; 339 } 340 mockingDetails(Object toInspect)341 public MockingDetails mockingDetails(Object toInspect) { 342 return new DefaultMockingDetails(toInspect); 343 } 344 lenient()345 public LenientStubber lenient() { 346 return new DefaultLenientStubber(); 347 } 348 clearAllCaches()349 public void clearAllCaches() { 350 MockUtil.clearAllCaches(); 351 } 352 } 353