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