public Object handle(Invocation invocation) throws Throwable { if (invocationContainerImpl.hasAnswersForStubbing()) { invocation.setPhase(InvocationPhase.DEFINE); // stubbing voids with stubVoid() or doAnswer() style InvocationMatcher invocationMatcher = matchersBinder.bindMatchers(mockingProgress.getArgumentMatcherStorage(), invocation); invocationContainerImpl.setMethodForStubbing(invocationMatcher); return null; } VerificationMode verificationMode = mockingProgress.pullVerificationMode(); InvocationMatcher invocationMatcher = matchersBinder.bindMatchers(mockingProgress.getArgumentMatcherStorage(), invocation); mockingProgress.validateState(); // if verificationMode is not null then someone is doing verify() if (verificationMode != null) { invocation.setPhase(InvocationPhase.VERIFY); // We need to check if verification was started on the correct mock // - see VerifyingWithAnExtraCallToADifferentMockTest (bug 138) if (((MockAwareVerificationMode) verificationMode).getMock() == invocation.getMock()) { VerificationDataImpl data = createVerificationData(invocationContainerImpl, invocationMatcher); verificationMode.verify(data); return null; } else { // this means there is an invocation on a different mock. Re-adding verification mode // - see VerifyingWithAnExtraCallToADifferentMockTest (bug 138) mockingProgress.verificationStarted(verificationMode); } } // prepare invocation for stubbing invocationContainerImpl.setInvocationForPotentialStubbing(invocationMatcher); OngoingStubbingImpl<T> ongoingStubbing = new OngoingStubbingImpl<T>(invocationContainerImpl); mockingProgress.reportOngoingStubbing(ongoingStubbing); // look for existing answer for this invocation StubbedInvocationMatcher stubbedInvocation = invocationContainerImpl.findAnswerFor(invocation); if (stubbedInvocation != null) { invocation.setPhase(InvocationPhase.EXECUTE); stubbedInvocation.captureArgumentsFrom(invocation); return stubbedInvocation.answer(invocation); } else { invocation.setPhase(InvocationPhase.DEFINE); Object ret = mockSettings.getDefaultAnswer().answer(invocation); // redo setting invocation for potential stubbing in case of partial // mocks / spies. // Without it, the real method inside 'when' might have delegated // to other self method and overwrite the intended stubbed method // with a different one. The reset is required to avoid runtime exception that validates // return type with stubbed method signature. invocationContainerImpl.resetInvocationForPotentialStubbing(invocationMatcher); return ret; } }