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.stubbing; 6 7 import java.io.Serializable; 8 import java.util.ArrayList; 9 import java.util.LinkedList; 10 import java.util.List; 11 import org.mockito.internal.invocation.InvocationMatcher; 12 import org.mockito.internal.invocation.StubInfoImpl; 13 import org.mockito.internal.verification.DefaultRegisteredInvocations; 14 import org.mockito.internal.verification.RegisteredInvocations; 15 import org.mockito.internal.verification.SingleRegisteredInvocation; 16 import org.mockito.invocation.Invocation; 17 import org.mockito.mock.MockCreationSettings; 18 import org.mockito.stubbing.Answer; 19 import org.mockito.stubbing.ValidableAnswer; 20 21 import static org.mockito.internal.progress.ThreadSafeMockingProgress.mockingProgress; 22 23 @SuppressWarnings("unchecked") 24 public class InvocationContainerImpl implements InvocationContainer, Serializable { 25 26 private static final long serialVersionUID = -5334301962749537177L; 27 private final LinkedList<StubbedInvocationMatcher> stubbed = new LinkedList<StubbedInvocationMatcher>(); 28 private final List<Answer<?>> answersForStubbing = new ArrayList<Answer<?>>(); 29 private final RegisteredInvocations registeredInvocations; 30 31 private InvocationMatcher invocationForStubbing; 32 InvocationContainerImpl(MockCreationSettings mockSettings)33 public InvocationContainerImpl(MockCreationSettings mockSettings) { 34 this.registeredInvocations = createRegisteredInvocations(mockSettings); 35 } 36 setInvocationForPotentialStubbing(InvocationMatcher invocation)37 public void setInvocationForPotentialStubbing(InvocationMatcher invocation) { 38 registeredInvocations.add(invocation.getInvocation()); 39 this.invocationForStubbing = invocation; 40 } 41 resetInvocationForPotentialStubbing(InvocationMatcher invocationMatcher)42 public void resetInvocationForPotentialStubbing(InvocationMatcher invocationMatcher) { 43 this.invocationForStubbing = invocationMatcher; 44 } 45 addAnswer(Answer answer)46 public void addAnswer(Answer answer) { 47 registeredInvocations.removeLast(); 48 addAnswer(answer, false); 49 } 50 addConsecutiveAnswer(Answer answer)51 public void addConsecutiveAnswer(Answer answer) { 52 addAnswer(answer, true); 53 } 54 55 /** 56 * Adds new stubbed answer and returns the invocation matcher the answer was added to. 57 */ addAnswer(Answer answer, boolean isConsecutive)58 public StubbedInvocationMatcher addAnswer(Answer answer, boolean isConsecutive) { 59 Invocation invocation = invocationForStubbing.getInvocation(); 60 mockingProgress().stubbingCompleted(); 61 if (answer instanceof ValidableAnswer) { 62 ((ValidableAnswer) answer).validateFor(invocation); 63 } 64 65 synchronized (stubbed) { 66 if (isConsecutive) { 67 stubbed.getFirst().addAnswer(answer); 68 } else { 69 stubbed.addFirst(new StubbedInvocationMatcher(invocationForStubbing, answer)); 70 } 71 return stubbed.getFirst(); 72 } 73 } 74 answerTo(Invocation invocation)75 Object answerTo(Invocation invocation) throws Throwable { 76 return findAnswerFor(invocation).answer(invocation); 77 } 78 findAnswerFor(Invocation invocation)79 public StubbedInvocationMatcher findAnswerFor(Invocation invocation) { 80 synchronized (stubbed) { 81 for (StubbedInvocationMatcher s : stubbed) { 82 if (s.matches(invocation)) { 83 s.markStubUsed(invocation); 84 invocation.markStubbed(new StubInfoImpl(s)); 85 return s; 86 } 87 } 88 } 89 90 return null; 91 } 92 addAnswerForVoidMethod(Answer answer)93 public void addAnswerForVoidMethod(Answer answer) { 94 answersForStubbing.add(answer); 95 } 96 setAnswersForStubbing(List<Answer<?>> answers)97 public void setAnswersForStubbing(List<Answer<?>> answers) { 98 answersForStubbing.addAll(answers); 99 } 100 hasAnswersForStubbing()101 public boolean hasAnswersForStubbing() { 102 return !answersForStubbing.isEmpty(); 103 } 104 hasInvocationForPotentialStubbing()105 public boolean hasInvocationForPotentialStubbing() { 106 return !registeredInvocations.isEmpty(); 107 } 108 setMethodForStubbing(InvocationMatcher invocation)109 public void setMethodForStubbing(InvocationMatcher invocation) { 110 invocationForStubbing = invocation; 111 assert hasAnswersForStubbing(); 112 for (int i = 0; i < answersForStubbing.size(); i++) { 113 addAnswer(answersForStubbing.get(i), i != 0); 114 } 115 answersForStubbing.clear(); 116 } 117 118 @Override toString()119 public String toString() { 120 return "invocationForStubbing: " + invocationForStubbing; 121 } 122 getInvocations()123 public List<Invocation> getInvocations() { 124 return registeredInvocations.getAll(); 125 } 126 clearInvocations()127 public void clearInvocations() { 128 registeredInvocations.clear(); 129 } 130 getStubbedInvocations()131 public List<StubbedInvocationMatcher> getStubbedInvocations() { 132 return stubbed; 133 } 134 invokedMock()135 public Object invokedMock() { 136 return invocationForStubbing.getInvocation().getMock(); 137 } 138 getInvocationForStubbing()139 public InvocationMatcher getInvocationForStubbing() { 140 return invocationForStubbing; 141 } 142 createRegisteredInvocations(MockCreationSettings mockSettings)143 private RegisteredInvocations createRegisteredInvocations(MockCreationSettings mockSettings) { 144 return mockSettings.isStubOnly() 145 ? new SingleRegisteredInvocation() 146 : new DefaultRegisteredInvocations(); 147 } 148 } 149