Piotr Piotr - 4 months ago 86
Java Question

Mockito calls real method from superclass when stubbing

I am getting problem with Mockito trying to call real method while stubbing. I assume this might be related to that method is inherited.
This is component external to my system and can't do really much about it. But let's get to the code

AbstractRpcClient abstractRpcClient = mock(AbstractRpcClient.class);
doNothing().when(abstractRpcClient).callOnce(anyString(), anyVararg());


Since
callOnce
calls methods on some other objects I get NPE right in the second line.
AbstractRpcClient
inherits from another abstract class, but this class is package local, so I can't even cast it in my stubbing.

Is there anything I can do about it? How can I stub this method to do nothing or throw exception WITHOUT calling real method.

Do I have to extend this class in test and override method
callOnce
? This of course works, but is there any other solution?

Minimal example:

package external.component;

public abstract class ClassToMock extends SuperClass {

}


abstract class SuperClass {
public void callOnce(String method, Object... params) {
throw new RuntimeException("We shouldn't be here");
}
}


Test class

package mypackage

import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.anyVararg;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock;

public class Testclass {

@Test
public void test() {
external.component.ClassToMock classToMock = mock(external.component.ClassToMock.class);
doNothing().when(classToMock).callOnce(anyString(), anyVararg());
}

}


In example of course
RuntimeException
is thrown from
callOnce
method.

Answer

It looks like bug in Mockito and actually it was already reported and was supposed to be fixed over a year ago:

https://github.com/mockito/mockito/issues/168

I am getting the same (broken) behaviour in versions 1.9.5 and most recent 1.10.19.

I would recommend that you raise the bug with Mockito.

As a temporary work-around there are a few options:

  • make the class public
  • add public void callOnce() { super.callOnce(); } in the child class