2 * Copyright (c) 2016 Red Hat, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.yangtools.testutils.mockito;
10 import com.google.common.annotations.Beta;
11 import java.io.Serializable;
12 import java.lang.reflect.Modifier;
13 import org.mockito.Mockito;
14 import org.mockito.invocation.InvocationOnMock;
15 import org.mockito.stubbing.Answer;
18 * Mockito Answer which for un-stubbed methods forwards the call to the real
19 * method if it is implemented on the mocked object (i.e. not an interface or
20 * abstract method), and otherwise throws an {@link UnstubbedMethodException}, like the
21 * {@link ThrowsMethodExceptionAnswer}.
24 * This can be useful to create light-weight <a href=
25 * "http://googletesting.blogspot.ch/2013/07/testing-on-toilet-know-your-test-doubles.html">Fake Doubles</a>
26 * (in particular some with state). For example:
29 * import static ...testutils.mockito.MoreAnswers.realOrException;
32 * List<Thing> getThings();
33 * boolean installThing(Thing thing);
36 * abstract class FakeService implements Service {
37 * // Ignore getThings() - we don't need that for this test
38 * boolean installThing(Thing thing) {
39 * LOGGER.log("not really installed");
44 * Service fake = Mockito.mock(FakeService.class, realOrException())
48 * TIP: An impact of Mockito is that, just like in standard Mockito, constructors
49 * (and thus field initializers) are not called. So in your abstract fake class,
53 * abstract class FakeService implements Service {
54 * private final List<Thing> things = new ArrayList<>();
56 * public List<Thing> getThings() {
61 * public boolean installThing(Thing thing) {
62 * return things.add(thing);
68 * you'll just need to do:
71 * abstract class FakeService implements Service {
72 * private List<Thing> things;
74 * public List<Thing> getThings() {
76 * things = new ArrayList<>()
81 * public boolean installThing(Thing thing) {
82 * return getThings().add(thing);
88 * The big advantage of Mikitos versus just writing classes implementing service
89 * interfaces without using Mockito at all is that you don't have to implement a
90 * lot of methods you don't care about - you can just make an abstract fake
91 * class (incl. e.g. an inner class in your Test) and implement only one or some
92 * methods. This keeps code shorter and thus more readable.
95 * The advantage of Mikitos VS pure Mockito's when/thenAnswer are that they:
98 * <li>are fully type safe and refactoring resistant; whereas Mockito is not,
99 * e.g. for return values with doReturn(...).when(), and uses runtime instead of
100 * compile time error reporting for this.</li>
101 * <li>avoid confusion re. the alternative doReturn(...).when() syntax required
102 * with ThrowsMethodExceptionAnswer instead of when(...).thenReturn()</li>
103 * <li>enforce the ThrowsMethodExceptionAnswer by default for
104 * non-implemented methods (which is possible with Mockito by explicitly passing
105 * this, but is easily forgotten)</li>
108 * @see Mockito#mock(Class, Answer)
109 * @see ThrowsMethodExceptionAnswer
110 * @see Mockito#CALLS_REAL_METHODS
111 * @see Mockito#CALLS_REAL_METHODS
113 * @author Michael Vorburger
116 public final class CallsRealOrExceptionAnswer implements Answer<Object>, Serializable {
117 private static final long serialVersionUID = -3730024662402964588L;
118 static final CallsRealOrExceptionAnswer INSTANCE = new CallsRealOrExceptionAnswer();
120 private CallsRealOrExceptionAnswer() {
125 public Object answer(final InvocationOnMock invocation) throws Throwable {
126 if (Modifier.isAbstract(invocation.getMethod().getModifiers())) {
127 throw new UnstubbedMethodException(invocation.getMethod(), invocation.getMock());
129 return invocation.callRealMethod();
132 Object readResolve() {