1e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson/* 2e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * Copyright (c) 2007 Mockito contributors 3e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * This program is made available under the terms of the MIT License. 4e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson */ 5e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonpackage org.mockito.internal.stubbing.defaultanswers; 6e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson 7e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport java.io.Serializable; 8e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport java.lang.reflect.Modifier; 9e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson 10e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport org.mockito.Mockito; 11e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport org.mockito.exceptions.Reporter; 12e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport org.mockito.internal.debugging.LocationImpl; 13e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport org.mockito.invocation.Location; 14e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport org.mockito.internal.util.ObjectMethodsGuru; 15e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport org.mockito.invocation.InvocationOnMock; 16e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonimport org.mockito.stubbing.Answer; 17e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson 18e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson/** 19e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * Optional Answer that can be used with 20e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * {@link Mockito#mock(Class, Answer)} 21e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * <p> 22e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * This implementation can be helpful when working with legacy code. Unstubbed 23e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * methods often return null. If your code uses the object returned by an 24e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * unstubbed call you get a NullPointerException. This implementation of 25e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * Answer returns SmartNulls instead of nulls. 26e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * SmartNull gives nicer exception message than NPE because it points out the 27e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * line where unstubbed method was called. You just click on the stack trace. 28e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * <p> 29e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * ReturnsSmartNulls first tries to return ordinary return values (see 30e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * {@link ReturnsMoreEmptyValues}) then it tries to return SmartNull. If the 31e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * return type is not mockable (e.g. final) then ordinary null is returned. 32e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * <p> 33e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * ReturnsSmartNulls will be probably the default return values strategy in 34e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson * Mockito 2.0 35e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson */ 36e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinsonpublic class ReturnsSmartNulls implements Answer<Object>, Serializable { 37e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson 38e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson private static final long serialVersionUID = 7618312406617949441L; 39e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson 40e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson private final Answer<Object> delegate = new ReturnsMoreEmptyValues(); 41e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson 42e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson public Object answer(final InvocationOnMock invocation) throws Throwable { 43e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson Object defaultReturnValue = delegate.answer(invocation); 44e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson if (defaultReturnValue != null) { 45e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson return defaultReturnValue; 46e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson } 47e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson Class<?> type = invocation.getMethod().getReturnType(); 48e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson if (!type.isPrimitive() && !Modifier.isFinal(type.getModifiers())) { 49e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson final Location location = new LocationImpl(); 50e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson return Mockito.mock(type, new ThrowsSmartNullPointer(invocation, location)); 51e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson } 52e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson return null; 53e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson } 54e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson 55e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson private static class ThrowsSmartNullPointer implements Answer { 56e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson private final InvocationOnMock unstubbedInvocation; 57e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson private final Location location; 58e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson 59e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson public ThrowsSmartNullPointer(InvocationOnMock unstubbedInvocation, Location location) { 60e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson this.unstubbedInvocation = unstubbedInvocation; 61e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson this.location = location; 62e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson } 63e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson 64e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson public Object answer(InvocationOnMock currentInvocation) throws Throwable { 65e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson if (new ObjectMethodsGuru().isToString(currentInvocation.getMethod())) { 66e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson return "SmartNull returned by this unstubbed method call on a mock:\n" + 67e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson unstubbedInvocation.toString(); 68e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson } 69e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson 70e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson new Reporter().smartNullPointerException(unstubbedInvocation.toString(), location); 71e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson return null; 72e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson } 73e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson } 74e0ae5d7e87b1dd6e789803c1b9615a84bd7488b7Ian Parkinson} 75