Class CallsRealOrExceptionAnswer

java.lang.Object
org.opendaylight.yangtools.testutils.mockito.CallsRealOrExceptionAnswer
All Implemented Interfaces:
Serializable, org.mockito.stubbing.Answer<Object>

@Beta public final class CallsRealOrExceptionAnswer extends Object implements org.mockito.stubbing.Answer<Object>, Serializable
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 UnstubbedMethodException, like the 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)
Author:
Michael Vorburger
See Also:
  • Method Details

    • answer

      public Object answer(org.mockito.invocation.InvocationOnMock invocation) throws Throwable
      Specified by:
      answer in interface org.mockito.stubbing.Answer<Object>
      Throws:
      Throwable