1 /* 2 * Copyright (c) 2016 Mockito contributors 3 * This program is made available under the terms of the MIT License. 4 */ 5 package org.mockito.internal.stubbing.defaultanswers; 6 7 import org.mockito.internal.util.JavaEightUtil; 8 import org.mockito.internal.util.MockUtil; 9 import org.mockito.internal.util.ObjectMethodsGuru; 10 import org.mockito.internal.util.Primitives; 11 import org.mockito.invocation.InvocationOnMock; 12 import org.mockito.mock.MockName; 13 import org.mockito.stubbing.Answer; 14 15 import static org.mockito.internal.util.ObjectMethodsGuru.isCompareToMethod; 16 import static org.mockito.internal.util.ObjectMethodsGuru.isToStringMethod; 17 18 import java.io.Serializable; 19 import java.util.*; 20 21 /** 22 * Default answer of every Mockito mock. 23 * <ul> 24 * <li> 25 * Returns appropriate primitive for primitive-returning methods 26 * </li> 27 * <li> 28 * Returns consistent values for primitive wrapper classes (e.g. int-returning method returns 0 <b>and</b> Integer-returning method returns 0, too) 29 * </li> 30 * <li> 31 * Returns empty collection for collection-returning methods (works for most commonly used collection types) 32 * </li> 33 * <li> 34 * Returns description of mock for toString() method 35 * </li> 36 * <li> 37 * Returns zero if references are equals otherwise non-zero for Comparable#compareTo(T other) method (see issue 184) 38 * </li> 39 * <li> 40 * Returns an {@code java.util.Optional#empty() empty Optional} for Optional. Similarly for primitive optional variants. 41 * </li> 42 * <li> 43 * Returns an {@code java.util.stream.Stream#empty() empty Stream} for Stream. Similarly for primitive stream variants. 44 * </li> 45 * <li> 46 * Returns null for everything else 47 * </li> 48 * </ul> 49 */ 50 public class ReturnsEmptyValues implements Answer<Object>, Serializable { 51 52 private static final long serialVersionUID = 1998191268711234347L; 53 54 55 /* (non-Javadoc) 56 * @see org.mockito.stubbing.Answer#answer(org.mockito.invocation.InvocationOnMock) 57 */ answer(InvocationOnMock invocation)58 public Object answer(InvocationOnMock invocation) { 59 if (isToStringMethod(invocation.getMethod())) { 60 Object mock = invocation.getMock(); 61 MockName name = MockUtil.getMockName(mock); 62 if (name.isDefault()) { 63 return "Mock for " + MockUtil.getMockSettings(mock).getTypeToMock().getSimpleName() + ", hashCode: " + mock.hashCode(); 64 } else { 65 return name.toString(); 66 } 67 } else if (isCompareToMethod(invocation.getMethod())) { 68 //see issue 184. 69 //mocks by default should return 0 if references are the same, otherwise some other value because they are not the same. Hence we return 1 (anything but 0 is good). 70 //Only for compareTo() method by the Comparable interface 71 return invocation.getMock() == invocation.getArgument(0) ? 0 : 1; 72 } 73 74 Class<?> returnType = invocation.getMethod().getReturnType(); 75 return returnValueFor(returnType); 76 } 77 returnValueFor(Class<?> type)78 Object returnValueFor(Class<?> type) { 79 if (Primitives.isPrimitiveOrWrapper(type)) { 80 return Primitives.defaultValue(type); 81 //new instances are used instead of Collections.emptyList(), etc. 82 //to avoid UnsupportedOperationException if code under test modifies returned collection 83 } else if (type == Iterable.class) { 84 return new ArrayList<Object>(0); 85 } else if (type == Collection.class) { 86 return new LinkedList<Object>(); 87 } else if (type == Set.class) { 88 return new HashSet<Object>(); 89 } else if (type == HashSet.class) { 90 return new HashSet<Object>(); 91 } else if (type == SortedSet.class) { 92 return new TreeSet<Object>(); 93 } else if (type == TreeSet.class) { 94 return new TreeSet<Object>(); 95 } else if (type == LinkedHashSet.class) { 96 return new LinkedHashSet<Object>(); 97 } else if (type == List.class) { 98 return new LinkedList<Object>(); 99 } else if (type == LinkedList.class) { 100 return new LinkedList<Object>(); 101 } else if (type == ArrayList.class) { 102 return new ArrayList<Object>(); 103 } else if (type == Map.class) { 104 return new HashMap<Object, Object>(); 105 } else if (type == HashMap.class) { 106 return new HashMap<Object, Object>(); 107 } else if (type == SortedMap.class) { 108 return new TreeMap<Object, Object>(); 109 } else if (type == TreeMap.class) { 110 return new TreeMap<Object, Object>(); 111 } else if (type == LinkedHashMap.class) { 112 return new LinkedHashMap<Object, Object>(); 113 } else if ("java.util.Optional".equals(type.getName())) { 114 return JavaEightUtil.emptyOptional(); 115 } else if ("java.util.OptionalDouble".equals(type.getName())) { 116 return JavaEightUtil.emptyOptionalDouble(); 117 } else if ("java.util.OptionalInt".equals(type.getName())) { 118 return JavaEightUtil.emptyOptionalInt(); 119 } else if ("java.util.OptionalLong".equals(type.getName())) { 120 return JavaEightUtil.emptyOptionalLong(); 121 } else if ("java.util.stream.Stream".equals(type.getName())) { 122 return JavaEightUtil.emptyStream(); 123 } else if ("java.util.stream.DoubleStream".equals(type.getName())) { 124 return JavaEightUtil.emptyDoubleStream(); 125 } else if ("java.util.stream.IntStream".equals(type.getName())) { 126 return JavaEightUtil.emptyIntStream(); 127 } else if ("java.util.stream.LongStream".equals(type.getName())) { 128 return JavaEightUtil.emptyLongStream(); 129 } 130 131 //Let's not care about the rest of collections. 132 return null; 133 } 134 } 135