Home | History | Annotate | Download | only in creation
      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
     44     public MockSettings serializable() {
     45         return serializable(SerializableMode.BASIC);
     46     }
     47 
     48     @Override
     49     public MockSettings serializable(SerializableMode mode) {
     50         this.serializableMode = mode;
     51         return this;
     52     }
     53 
     54     @Override
     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
     72     public MockName getMockName() {
     73         return mockName;
     74     }
     75 
     76     @Override
     77     public Set<Class<?>> getExtraInterfaces() {
     78         return extraInterfaces;
     79     }
     80 
     81     @Override
     82     public Object getSpiedInstance() {
     83         return spiedInstance;
     84     }
     85 
     86     @Override
     87     public MockSettings name(String name) {
     88         this.name = name;
     89         return this;
     90     }
     91 
     92     @Override
     93     public MockSettings spiedInstance(Object spiedInstance) {
     94         this.spiedInstance = spiedInstance;
     95         return this;
     96     }
     97 
     98     @Override
     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
    108     public Answer<Object> getDefaultAnswer() {
    109         return defaultAnswer;
    110     }
    111 
    112     @Override
    113     public MockSettingsImpl<T> stubOnly() {
    114         this.stubOnly = true;
    115         return this;
    116     }
    117 
    118     @Override
    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
    129     public MockSettings outerInstance(Object outerClassInstance) {
    130         this.outerClassInstance = outerClassInstance;
    131         return this;
    132     }
    133 
    134     @Override
    135     public MockSettings withoutAnnotations() {
    136         stripAnnotations = true;
    137         return this;
    138     }
    139 
    140     @Override
    141     public boolean isUsingConstructor() {
    142         return useConstructor;
    143     }
    144 
    145     @Override
    146     public Object getOuterClassInstance() {
    147         return outerClassInstance;
    148     }
    149 
    150     @Override
    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
    162     public boolean isStubOnly() {
    163         return this.stubOnly;
    164     }
    165 
    166     @Override
    167     public MockSettings verboseLogging() {
    168         if (!invocationListenersContainsType(VerboseMockInvocationLogger.class)) {
    169             invocationListeners(new VerboseMockInvocationLogger());
    170         }
    171         return this;
    172     }
    173 
    174     @Override
    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 
    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
    196     public MockSettings verificationStartedListeners(VerificationStartedListener... listeners) {
    197         addListeners(listeners, this.verificationStartedListeners, "verificationStartedListeners");
    198         return this;
    199     }
    200 
    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
    211     public List<InvocationListener> getInvocationListeners() {
    212         return this.invocationListeners;
    213     }
    214 
    215     public boolean hasInvocationListeners() {
    216         return !invocationListeners.isEmpty();
    217     }
    218 
    219     @Override
    220     public Class<T> getTypeToMock() {
    221         return typeToMock;
    222     }
    223 
    224     @Override
    225     public <T> MockCreationSettings<T> build(Class<T> typeToMock) {
    226         return validatedSettings(typeToMock, (CreationSettings<T>) this);
    227     }
    228 
    229     private static <T> CreationSettings<T> validatedSettings(Class<T> typeToMock, CreationSettings<T> source) {
    230         MockCreationValidator validator = new MockCreationValidator();
    231 
    232         validator.validateType(typeToMock);
    233         validator.validateExtraInterfaces(typeToMock, source.getExtraInterfaces());
    234         validator.validateMockedType(typeToMock, source.getSpiedInstance());
    235 
    236         //TODO SF - add this validation and also add missing coverage
    237 //        validator.validateDelegatedInstance(classToMock, settings.getDelegatedInstance());
    238 
    239         validator.validateConstructorUse(source.isUsingConstructor(), source.getSerializableMode());
    240 
    241         //TODO SF - I don't think we really need CreationSettings type
    242         //TODO do we really need to copy the entire settings every time we create mock object? it does not seem necessary.
    243         CreationSettings<T> settings = new CreationSettings<T>(source);
    244         settings.setMockName(new MockNameImpl(source.getName(), typeToMock));
    245         settings.setTypeToMock(typeToMock);
    246         settings.setExtraInterfaces(prepareExtraInterfaces(source));
    247         return settings;
    248     }
    249 
    250     private static Set<Class<?>> prepareExtraInterfaces(CreationSettings settings) {
    251         Set<Class<?>> interfaces = new HashSet<Class<?>>(settings.getExtraInterfaces());
    252         if(settings.isSerializable()) {
    253             interfaces.add(Serializable.class);
    254         }
    255         return interfaces;
    256     }
    257 
    258 }
    259 
    260