com.fitbur.mockito.internal.handler.MockHandlerImpl Maven / Gradle / Ivy
/*
* Copyright (c) 2007 Mockito contributors
* This program is made available under the terms of the MIT License.
*/
package com.fitbur.mockito.internal.handler;
import com.fitbur.mockito.internal.InternalMockHandler;
import com.fitbur.mockito.internal.invocation.InvocationMatcher;
import com.fitbur.mockito.internal.invocation.MatchersBinder;
import com.fitbur.mockito.internal.progress.MockingProgress;
import com.fitbur.mockito.internal.progress.ThreadSafeMockingProgress;
import com.fitbur.mockito.internal.stubbing.InvocationContainer;
import com.fitbur.mockito.internal.stubbing.InvocationContainerImpl;
import com.fitbur.mockito.internal.stubbing.OngoingStubbingImpl;
import com.fitbur.mockito.internal.stubbing.StubbedInvocationMatcher;
import com.fitbur.mockito.internal.stubbing.answers.AnswersValidator;
import com.fitbur.mockito.internal.verification.MockAwareVerificationMode;
import com.fitbur.mockito.internal.verification.VerificationDataImpl;
import com.fitbur.mockito.invocation.Invocation;
import com.fitbur.mockito.mock.MockCreationSettings;
import com.fitbur.mockito.stubbing.Answer;
import com.fitbur.mockito.verification.VerificationMode;
import java.util.List;
import static com.fitbur.mockito.exceptions.Reporter.stubPassedToVerify;
/**
* Invocation handler set on mock objects.
*
* @param type of mock object to handle
*/
class MockHandlerImpl implements InternalMockHandler {
private static final long serialVersionUID = -2917871070982574165L;
InvocationContainerImpl invocationContainerImpl;
MatchersBinder matchersBinder = new MatchersBinder();
MockingProgress mockingProgress = new ThreadSafeMockingProgress();
private final MockCreationSettings mockSettings;
public MockHandlerImpl(MockCreationSettings mockSettings) {
this.mockSettings = mockSettings;
this.mockingProgress = new ThreadSafeMockingProgress();
this.matchersBinder = new MatchersBinder();
this.invocationContainerImpl = new InvocationContainerImpl(mockingProgress, mockSettings);
}
public Object handle(Invocation invocation) throws Throwable {
if (invocationContainerImpl.hasAnswersForStubbing()) {
// stubbing voids with doThrow() 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) {
// 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 ongoingStubbing = new OngoingStubbingImpl(invocationContainerImpl);
mockingProgress.reportOngoingStubbing(ongoingStubbing);
// look for existing answer for this invocation
StubbedInvocationMatcher stubbedInvocation = invocationContainerImpl.findAnswerFor(invocation);
if (stubbedInvocation != null) {
stubbedInvocation.captureArgumentsFrom(invocation);
return stubbedInvocation.answer(invocation);
} else {
Object ret = mockSettings.getDefaultAnswer().answer(invocation);
new AnswersValidator().validateDefaultAnswerReturnedValue(invocation, ret);
// 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;
}
}
public MockCreationSettings getMockSettings() {
return mockSettings;
}
@SuppressWarnings("unchecked")
public void setAnswersForStubbing(List> answers) {
invocationContainerImpl.setAnswersForStubbing(answers);
}
public InvocationContainer getInvocationContainer() {
return invocationContainerImpl;
}
private VerificationDataImpl createVerificationData(InvocationContainerImpl invocationContainerImpl, InvocationMatcher invocationMatcher) {
if (mockSettings.isStubOnly()) {
throw stubPassedToVerify(); // this throws an exception
}
return new VerificationDataImpl(invocationContainerImpl, invocationMatcher);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy