/* * * * Copyright 2010, Unitils.org * * * * Licensed under the Apache License, Version 2.0 (the "License"); * * you may not use this file except in compliance with the License. * * You may obtain a copy of the License at * * * * http://www.apache.org/licenses/LICENSE-2.0 * * * * Unless required by applicable law or agreed to in writing, software * * distributed under the License is distributed on an "AS IS" BASIS, * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * * See the License for the specific language governing permissions and * * limitations under the License. * */ package org.unitils.mock.core.matching.impl; import org.unitils.mock.Mock; import org.unitils.mock.argumentmatcher.ArgumentMatcher; import org.unitils.mock.core.BehaviorDefiningInvocation; import org.unitils.mock.core.BehaviorDefiningInvocations; import org.unitils.mock.core.MockFactory; import org.unitils.mock.core.matching.MatchingInvocationHandler; import org.unitils.mock.core.proxy.ProxyInvocation; import org.unitils.mock.mockbehavior.MockBehavior; import org.unitils.mock.mockbehavior.impl.ValueReturningMockBehavior; import java.util.List; import static org.unitils.core.util.ObjectFormatter.MOCK_NAME_CHAIN_SEPARATOR; /** * @author Tim Ducheyne * @author Filip Neven */ public class BehaviorDefiningMatchingInvocationHandler implements MatchingInvocationHandler { protected MockBehavior mockBehavior; protected MockFactory mockFactory; protected BehaviorDefiningInvocations behaviorDefiningInvocations; public BehaviorDefiningMatchingInvocationHandler(MockBehavior mockBehavior, BehaviorDefiningInvocations behaviorDefiningInvocations, MockFactory mockFactory) { this.mockBehavior = mockBehavior; this.behaviorDefiningInvocations = behaviorDefiningInvocations; this.mockFactory = mockFactory; } public Object handleInvocation(ProxyInvocation proxyInvocation, List<ArgumentMatcher> argumentMatchers) throws Throwable { if (mockBehavior instanceof ChainedMockBehavior) { ((ChainedMockBehavior) mockBehavior).installChain(); } BehaviorDefiningInvocation behaviorDefiningInvocation = new BehaviorDefiningInvocation(proxyInvocation, mockBehavior, argumentMatchers); addBehaviorDefiningInvocation(behaviorDefiningInvocation, behaviorDefiningInvocations); return createChainedMock(proxyInvocation, behaviorDefiningInvocation); } protected void addBehaviorDefiningInvocation(BehaviorDefiningInvocation behaviorDefiningInvocation, BehaviorDefiningInvocations behaviorDefinition) { behaviorDefinition.addBehaviorDefiningInvocation(behaviorDefiningInvocation); } protected Object createChainedMock(ProxyInvocation proxyInvocation, BehaviorDefiningInvocation behaviorDefiningInvocation) { Class<?> innerMockType = proxyInvocation.getMethod().getReturnType(); String innerMockName = proxyInvocation.getMockName() + MOCK_NAME_CHAIN_SEPARATOR + proxyInvocation.getMethod().getName(); Mock<?> mock = mockFactory.createChainedMock(innerMockName, innerMockType); if (mock == null) { return null; } return mock.performs(new ChainedMockBehavior(mock, behaviorDefiningInvocation)); } public static class ChainedMockBehavior implements MockBehavior { protected Mock<?> mock; protected BehaviorDefiningInvocation behaviorDefiningInvocation; protected MockBehavior originalMockBehavior; public ChainedMockBehavior(Mock<?> mock, BehaviorDefiningInvocation behaviorDefiningInvocation) { this.mock = mock; this.behaviorDefiningInvocation = behaviorDefiningInvocation; this.originalMockBehavior = behaviorDefiningInvocation.getMockBehavior(); } public void installChain() { behaviorDefiningInvocation.setMockBehavior(new ValueReturningMockBehavior(mock.getMock())); } public Object execute(ProxyInvocation proxyInvocation) throws Throwable { return originalMockBehavior.execute(proxyInvocation); } } }