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.stubbing.answers;
6 
7 import java.io.Serializable;
8 import java.lang.reflect.Modifier;
9 import org.mockito.invocation.InvocationOnMock;
10 import org.mockito.stubbing.Answer;
11 import org.mockito.stubbing.ValidableAnswer;
12 
13 import static org.mockito.Answers.RETURNS_DEFAULTS;
14 import static org.mockito.internal.exceptions.Reporter.cannotCallAbstractRealMethod;
15 
16 /**
17  * Optional Answer that adds partial mocking support
18  * <p>
19  * {@link Answer} can be used to define the return values of unstubbed invocations.
20  * <p>
21  * This implementation can be helpful when working with legacy code.
22  * When this implementation is used, unstubbed methods will delegate to the real implementation.
23  * This is a way to create a partial mock object that calls real methods by default.
24  * <p>
25  * As usual you are going to read <b>the partial mock warning</b>:
26  * Object oriented programming is more less tackling complexity by dividing the complexity into separate, specific, SRPy objects.
27  * How does partial mock fit into this paradigm? Well, it just doesn't...
28  * Partial mock usually means that the complexity has been moved to a different method on the same object.
29  * In most cases, this is not the way you want to design your application.
30  * <p>
31  * However, there are rare cases when partial mocks come handy:
32  * dealing with code you cannot change easily (3rd party interfaces, interim refactoring of legacy code etc.)
33  * However, I wouldn't use partial mocks for new, test-driven & well-designed code.
34  * <p>
35  */
36 public class CallsRealMethods implements Answer<Object>, ValidableAnswer, Serializable {
37     private static final long serialVersionUID = 9057165148930624087L;
38 
answer(InvocationOnMock invocation)39     public Object answer(InvocationOnMock invocation) throws Throwable {
40         if (Modifier.isAbstract(invocation.getMethod().getModifiers())) {
41             return RETURNS_DEFAULTS.answer(invocation);
42         }
43         return invocation.callRealMethod();
44     }
45 
46     @Override
validateFor(InvocationOnMock invocation)47     public void validateFor(InvocationOnMock invocation) {
48         if (new InvocationInfo(invocation).isAbstract()) {
49             throw cannotCallAbstractRealMethod();
50         }
51     }
52 }
53