Is it possible to call standard implementation of interfaces using Mockito doCallRealMethod?

Suppose I have the following interface:

public interface ISomething { default int doStuff() { return 2 * getValue(); } int getValue(); } 

When I am mocking this interface as follows:

 @Mock private ISomething _something; @Before public void setup() { doCallRealMethod().when(_something).doStuff(); } 

and try checking the doStuff () method as follows:

 @Test public void testDoStuff() { when(_something.getValue()).thenReturn(42); assertThat("doStuff() returns 84", _something.doStuff(), is(84)); } 

I expect the test to succeed, but I get:

 org.mockito.exceptions.base.MockitoException: Cannot call real method on java interface. Interface does not have any implementation! Calling real methods is only possible when mocking concrete classes. 

I tried subclassing ISomething with an abstract class as follows:

 public abstract class Something implements ISomething { } 

and make fun of this class as stated above. With this approach, I get the same thing.

Does Mockito help support default calls?

+6
source share
2 answers

It is right. The current version of Mockito does not support this. You can raise the function request here . Please note that this is due to issue 456, which was fixed in version 1.10.0, so check it first in the latest version.

+3
source

I was working on a project using Mockito 1.9.5 and ran into the same issue as you. We were unable to update Mockito due to the operation of our build server. The problem that we encountered was that we wrote unit tests for specific subclasses, since we could not drown or include default methods from the interface in our dummy objects (slightly different from your example).

Here is an example of a subclass using your model:

 public class ConcreteSomething implements ISomething { @Override int getValue() { return 42; } } 

Then, in the unit test class, we explicitly created a closed inner class. This class overrides all the standard methods of the tested concrete class (i.e. ConcreteSomething ) with the default interface implementation. So in this example something like:

 private class ConcreteSomethingDefaultImpl extends ConcreteSomething { @Override int doStuff() { return super.doStuff(); } } 

For us, a mock created using mock(ConcreteSomething.class) could not have default methods called with doCallRealMethod() , but mock(ConcreteSomethingDefaultImpl.class) could, and more importantly, it was the default implementation code in the interface. which was used.

I hope this helps anyone who is forced to use a specific version of Mockito.

0
source

Source: https://habr.com/ru/post/978689/


All Articles