Mockito: Trying to spy on method is calling the original method

97
July 16, 2017, at 8:59 PM

I'm using Mockito 1.9.0. I want mock the behaviour for a single method of a class in a JUnit test, so I have

final MyClass myClassSpy = Mockito.spy(myInstance);
Mockito.when(myClassSpy.method1()).thenReturn(myResults);

The problem is, in the second line, myClassSpy.method1() is actually getting called, resulting in an exception. The only reason I'm using mocks is so that later, whenever myClassSpy.method1() is called, the real method won't be called and the myResults object will be returned.

MyClass is an interface and myInstance is an implementation of that, if that matters.

What do I need to do to correct this spying behaviour?

Answer 1

Let me quote the official documentation:

Important gotcha on spying real objects!

Sometimes it's impossible to use when(Object) for stubbing spies. Example:

List list = new LinkedList();
List spy = spy(list);
//Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty)
when(spy.get(0)).thenReturn("foo");
//You have to use doReturn() for stubbing
doReturn("foo").when(spy).get(0);

In your case it goes something like:

doReturn(resulstIWant).when(myClassSpy).method1();
Answer 2

My case was different from the accepted answer. I was trying to mock a package-private method for an instance that did not live in that package

package common;
public class AnimalĀ {
  void packageProtected();
}
package instances;
class Dog extends Animal { }

and the test classes

package common;
public abstract class AnimalTest<T extends Animal> {
  @Before
  setup(){
    doNothing().when(getInstance()).packageProtected();
  }
  abstract T getInstance();
}
package instances;
class DogTest extends AnimalTest<Dog> {
  Dog getInstance(){
    return spy(new Dog());
  }
  @Test
  public void myTest(){}
}

The compilation is correct, but when it tries to setup the test, it invokes the real method instead.

Declaring the method protected or public fixes the issue, tho it's not a clean solution.

Answer 3

The answer by Tomasz Nurkiewicz appears not to tell the whole story!

NB Mockito version: 1.10.19.

I am very much a Mockito newb, so can't explain the following behaviour: if there's an expert out there who can improve this answer, please feel free.

The method in question here, getContentStringValue, is NOT final and NOT static.

This line does call the original method getContentStringValue:

doReturn( "dummy" ).when( im ).getContentStringValue( anyInt(), isA( ScoreDoc.class ));

This line does not call the original method getContentStringValue:

doReturn( "dummy" ).when( im ).getContentStringValue( anyInt(), any( ScoreDoc.class ));

For reasons which I can't answer, using isA() causes the intended (?) "do not call method" behaviour of doReturn to fail.

Let's look at the method signatures involved here: they are both static methods of Matchers. Both are said by the Javadoc to return null, which is a little difficult to get your head around in itself. Presumably the Class object passed as the parameter is examined but the result either never calculated or discarded. Given that null can stand for any class and that you are hoping for the mocked method not to be called, couldn't the signatures of isA( ... ) and any( ... ) just return null rather than a generic parameter* <T>?

Anyway:

public static <T> T isA(java.lang.Class<T> clazz)
public static <T> T any(java.lang.Class<T> clazz)

The API documentation does not give any clue about this. It also seems to say the need for such "do not call method" behaviour is "very rare". Personally I use this technique all the time: typically I find that mocking involves a few lines which "set the scene" ... followed by calling a method which then "plays out" the scene in the mock context which you have staged... and while you are setting up the scenery and the props the last thing you want is for the actors to enter stage left and start acting their hearts out...

But this is way beyond my pay grade... I invite explanations from any passing Mockito high priests...

* is "generic parameter" the right term?

Answer 4

In my case, using Mockito 2.0, I had to change all the any() parameters to nullable() in order to stub the real call.

READ ALSO
Every time open app , open last open activity

Every time open app , open last open activity

Sir, The last opened activity will be saved and when opening the app, the last opened activity will be openedBut app reopen every time then see splash screen then go last open activity, Please help me for it

81
Run Spring boot .jar file with spring.config.location with replace values of application.properties?

Run Spring boot .jar file with spring.config.location with replace values of application.properties?

When I run a Spring boot application from command line with --springconfig

103
Understanding Apache Tomcat Connection Pooling

Understanding Apache Tomcat Connection Pooling

I am trying to implement Apache Tomcat's built-in JDBC connection poolBut I am confused with many things

73