• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.creation;
6 
7 import org.mockito.MockSettings;
8 import org.mockito.internal.creation.settings.CreationSettings;
9 import org.mockito.internal.debugging.VerboseMockInvocationLogger;
10 import org.mockito.internal.util.Checks;
11 import org.mockito.internal.util.MockCreationValidator;
12 import org.mockito.internal.util.MockNameImpl;
13 import org.mockito.listeners.InvocationListener;
14 import org.mockito.listeners.VerificationStartedListener;
15 import org.mockito.mock.MockCreationSettings;
16 import org.mockito.mock.MockName;
17 import org.mockito.mock.SerializableMode;
18 import org.mockito.stubbing.Answer;
19 
20 import java.io.Serializable;
21 import java.util.ArrayList;
22 import java.util.Arrays;
23 import java.util.HashSet;
24 import java.util.List;
25 import java.util.Set;
26 
27 import static org.mockito.internal.exceptions.Reporter.defaultAnswerDoesNotAcceptNullParameter;
28 import static org.mockito.internal.exceptions.Reporter.extraInterfacesAcceptsOnlyInterfaces;
29 import static org.mockito.internal.exceptions.Reporter.extraInterfacesDoesNotAcceptNullParameters;
30 import static org.mockito.internal.exceptions.Reporter.extraInterfacesRequiresAtLeastOneInterface;
31 import static org.mockito.internal.exceptions.Reporter.invocationListenersRequiresAtLeastOneListener;
32 import static org.mockito.internal.exceptions.Reporter.methodDoesNotAcceptParameter;
33 import static org.mockito.internal.util.collections.Sets.newSet;
34 
35 @SuppressWarnings("unchecked")
36 public class MockSettingsImpl<T> extends CreationSettings<T> implements MockSettings, MockCreationSettings<T> {
37 
38     private static final long serialVersionUID = 4475297236197939569L;
39     private boolean useConstructor;
40     private Object outerClassInstance;
41     private Object[] constructorArgs;
42 
43     @Override
serializable()44     public MockSettings serializable() {
45         return serializable(SerializableMode.BASIC);
46     }
47 
48     @Override
serializable(SerializableMode mode)49     public MockSettings serializable(SerializableMode mode) {
50         this.serializableMode = mode;
51         return this;
52     }
53 
54     @Override
extraInterfaces(Class<?>.... extraInterfaces)55     public MockSettings extraInterfaces(Class<?>... extraInterfaces) {
56         if (extraInterfaces == null || extraInterfaces.length == 0) {
57             throw extraInterfacesRequiresAtLeastOneInterface();
58         }
59 
60         for (Class<?> i : extraInterfaces) {
61             if (i == null) {
62                 throw extraInterfacesDoesNotAcceptNullParameters();
63             } else if (!i.isInterface()) {
64                 throw extraInterfacesAcceptsOnlyInterfaces(i);
65             }
66         }
67         this.extraInterfaces = newSet(extraInterfaces);
68         return this;
69     }
70 
71     @Override
getMockName()72     public MockName getMockName() {
73         return mockName;
74     }
75 
76     @Override
getExtraInterfaces()77     public Set<Class<?>> getExtraInterfaces() {
78         return extraInterfaces;
79     }
80 
81     @Override
getSpiedInstance()82     public Object getSpiedInstance() {
83         return spiedInstance;
84     }
85 
86     @Override
name(String name)87     public MockSettings name(String name) {
88         this.name = name;
89         return this;
90     }
91 
92     @Override
spiedInstance(Object spiedInstance)93     public MockSettings spiedInstance(Object spiedInstance) {
94         this.spiedInstance = spiedInstance;
95         return this;
96     }
97 
98     @Override
defaultAnswer(Answer defaultAnswer)99     public MockSettings defaultAnswer(Answer defaultAnswer) {
100         this.defaultAnswer = defaultAnswer;
101         if (defaultAnswer == null) {
102             throw defaultAnswerDoesNotAcceptNullParameter();
103         }
104         return this;
105     }
106 
107     @Override
getDefaultAnswer()108     public Answer<Object> getDefaultAnswer() {
109         return defaultAnswer;
110     }
111 
112     @Override
stubOnly()113     public MockSettingsImpl<T> stubOnly() {
114         this.stubOnly = true;
115         return this;
116     }
117 
118     @Override
useConstructor(Object... constructorArgs)119     public MockSettings useConstructor(Object... constructorArgs) {
120         Checks.checkNotNull(constructorArgs,
121             "constructorArgs",
122             "If you need to pass null, please cast it to the right type, e.g.: useConstructor((String) null)");
123         this.useConstructor = true;
124         this.constructorArgs = constructorArgs;
125         return this;
126     }
127 
128     @Override
outerInstance(Object outerClassInstance)129     public MockSettings outerInstance(Object outerClassInstance) {
130         this.outerClassInstance = outerClassInstance;
131         return this;
132     }
133 
134     @Override
withoutAnnotations()135     public MockSettings withoutAnnotations() {
136         stripAnnotations = true;
137         return this;
138     }
139 
140     @Override
isUsingConstructor()141     public boolean isUsingConstructor() {
142         return useConstructor;
143     }
144 
145     @Override
getOuterClassInstance()146     public Object getOuterClassInstance() {
147         return outerClassInstance;
148     }
149 
150     @Override
getConstructorArgs()151     public Object[] getConstructorArgs() {
152         if (outerClassInstance == null) {
153             return constructorArgs;
154         }
155         List<Object> resultArgs = new ArrayList<Object>(constructorArgs.length + 1);
156         resultArgs.add(outerClassInstance);
157         resultArgs.addAll(Arrays.asList(constructorArgs));
158         return resultArgs.toArray(new Object[constructorArgs.length + 1]);
159     }
160 
161     @Override
isStubOnly()162     public boolean isStubOnly() {
163         return this.stubOnly;
164     }
165 
166     @Override
verboseLogging()167     public MockSettings verboseLogging() {
168         if (!invocationListenersContainsType(VerboseMockInvocationLogger.class)) {
169             invocationListeners(new VerboseMockInvocationLogger());
170         }
171         return this;
172     }
173 
174     @Override
invocationListeners(InvocationListener... listeners)175     public MockSettings invocationListeners(InvocationListener... listeners) {
176         if (listeners == null || listeners.length == 0) {
177             throw invocationListenersRequiresAtLeastOneListener();
178         }
179         addListeners(listeners, invocationListeners, "invocationListeners");
180         return this;
181     }
182 
addListeners(T[] listeners, List<T> container, String method)183     private static <T> void addListeners(T[] listeners, List<T> container, String method) {
184         if (listeners == null) {
185             throw methodDoesNotAcceptParameter(method, "null vararg array.");
186         }
187         for (T listener : listeners) {
188             if (listener == null) {
189                 throw methodDoesNotAcceptParameter(method, "null listeners.");
190             }
191             container.add(listener);
192         }
193     }
194 
195     @Override
verificationStartedListeners(VerificationStartedListener... listeners)196     public MockSettings verificationStartedListeners(VerificationStartedListener... listeners) {
197         addListeners(listeners, this.verificationStartedListeners, "verificationStartedListeners");
198         return this;
199     }
200 
invocationListenersContainsType(Class<?> clazz)201     private boolean invocationListenersContainsType(Class<?> clazz) {
202         for (InvocationListener listener : invocationListeners) {
203             if (listener.getClass().equals(clazz)) {
204                 return true;
205             }
206         }
207         return false;
208     }
209 
210     @Override
getInvocationListeners()211     public List<InvocationListener> getInvocationListeners() {
212         return this.invocationListeners;
213     }
214 
hasInvocationListeners()215     public boolean hasInvocationListeners() {
216         return !invocationListeners.isEmpty();
217     }
218 
219     @Override
getTypeToMock()220     public Class<T> getTypeToMock() {
221         return typeToMock;
222     }
223 
224     @Override
build(Class<T> typeToMock)225     public <T> MockCreationSettings<T> build(Class<T> typeToMock) {
226         return validatedSettings(typeToMock, (CreationSettings<T>) this);
227     }
228 
229     @Override
lenient()230     public MockSettings lenient() {
231         this.lenient = true;
232         return this;
233     }
234 
validatedSettings(Class<T> typeToMock, CreationSettings<T> source)235     private static <T> CreationSettings<T> validatedSettings(Class<T> typeToMock, CreationSettings<T> source) {
236         MockCreationValidator validator = new MockCreationValidator();
237 
238         validator.validateType(typeToMock);
239         validator.validateExtraInterfaces(typeToMock, source.getExtraInterfaces());
240         validator.validateMockedType(typeToMock, source.getSpiedInstance());
241 
242         //TODO SF - add this validation and also add missing coverage
243 //        validator.validateDelegatedInstance(classToMock, settings.getDelegatedInstance());
244 
245         validator.validateConstructorUse(source.isUsingConstructor(), source.getSerializableMode());
246 
247         //TODO SF - I don't think we really need CreationSettings type
248         //TODO do we really need to copy the entire settings every time we create mock object? it does not seem necessary.
249         CreationSettings<T> settings = new CreationSettings<T>(source);
250         settings.setMockName(new MockNameImpl(source.getName(), typeToMock));
251         settings.setTypeToMock(typeToMock);
252         settings.setExtraInterfaces(prepareExtraInterfaces(source));
253         return settings;
254     }
255 
prepareExtraInterfaces(CreationSettings settings)256     private static Set<Class<?>> prepareExtraInterfaces(CreationSettings settings) {
257         Set<Class<?>> interfaces = new HashSet<Class<?>>(settings.getExtraInterfaces());
258         if(settings.isSerializable()) {
259             interfaces.add(Serializable.class);
260         }
261         return interfaces;
262     }
263 
264 }
265 
266