org.opendaylight.yangtools.testutils.mockito.CallsRealOrExceptionAnswer Maven / Gradle / Ivy
/*
* Copyright (c) 2016 Red Hat, Inc. and others. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
package org.opendaylight.yangtools.testutils.mockito;
import com.google.common.annotations.Beta;
import java.io.Serializable;
import java.lang.reflect.Modifier;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
/**
* Mockito Answer which for un-stubbed methods forwards the call to the real
* method if it is implemented on the mocked object (i.e. not an interface or
* abstract method), and otherwise throws an {@link UnstubbedMethodException}, like the
* {@link ThrowsMethodExceptionAnswer}.
*
*
* This can be useful to create light-weight Fake Doubles
* (in particular some with state). For example:
*
*
* import static ...testutils.mockito.MoreAnswers.realOrException;
*
* interface Service {
* List<Thing> getThings();
* boolean installThing(Thing thing);
* }
*
* abstract class FakeService implements Service {
* // Ignore getThings() - we don't need that for this test
* boolean installThing(Thing thing) {
* LOGGER.log("not really installed");
* return false;
* }
* }
*
* Service fake = Mockito.mock(FakeService.class, realOrException())
*
*
*
* TIP: An impact of Mockito is that, just like in standard Mockito, constructors
* (and thus field initializers) are not called. So in your abstract fake class,
* instead of:
*
*
* abstract class FakeService implements Service {
* private final List<Thing> things = new ArrayList<>();
*
* public List<Thing> getThings() {
* return things;
* }
*
* @Override
* public boolean installThing(Thing thing) {
* return things.add(thing);
* }
* }
*
*
*
* you'll just need to do:
*
*
* abstract class FakeService implements Service {
* private List<Thing> things;
*
* public List<Thing> getThings() {
* if (things == null)
* things = new ArrayList<>()
* return things;
* }
*
* @Override
* public boolean installThing(Thing thing) {
* return getThings().add(thing);
* }
* }
*
*
*
* The big advantage of Mikitos versus just writing classes implementing service
* interfaces without using Mockito at all is that you don't have to implement a
* lot of methods you don't care about - you can just make an abstract fake
* class (incl. e.g. an inner class in your Test) and implement only one or some
* methods. This keeps code shorter and thus more readable.
*
*
* The advantage of Mikitos VS pure Mockito's when/thenAnswer are that they:
*
*
* - are fully type safe and refactoring resistant; whereas Mockito is not,
* e.g. for return values with doReturn(...).when(), and uses runtime instead of
* compile time error reporting for this.
* - avoid confusion re. the alternative doReturn(...).when() syntax required
* with ThrowsMethodExceptionAnswer instead of when(...).thenReturn()
* - enforce the ThrowsMethodExceptionAnswer by default for
* non-implemented methods (which is possible with Mockito by explicitly passing
* this, but is easily forgotten)
*
*
* @see Mockito#mock(Class, Answer)
* @see ThrowsMethodExceptionAnswer
* @see Mockito#CALLS_REAL_METHODS
* @see Mockito#CALLS_REAL_METHODS
*
* @author Michael Vorburger
*/
@Beta
public final class CallsRealOrExceptionAnswer implements Answer