0

I am trying to mock a call to a protected method of one of my classes:

import com.couchbase.client.java.view.Stale; // an enum
import com.google.common.base.Optional;

public class MyClass {
  public List<String> myList(Optional<Integer> arg1, Optional<Stale> arg2) {
    ...
  }
}

The mock shall be accomplished in the following way:

// Providing types for any() does not change anything
Mockito.when(myClass.myList(Mockito.any(), Mockito.any()).thenReturn(new ArrayList());

Whenever the previous line is executed the actual myList() method is called with null values for arg1 and arg2. Why is the method called, at all? After all, I am trying to avoid any executing thereof...

Bastian
  • 4,638
  • 6
  • 36
  • 55

2 Answers2

3

As Brice mentioned, if your myList method is final, then Java skips virtual method dispatch and will call the original object (not your mock).

If you are spying on an actual class, it is expected behavior that when will call the actual object as part of the stub: after all, in the expression when(foo.bar()) Java doesn't know anything special about when and assumes that it cares about the return value) of foo.bar(), not the call itself. (I walk through the stubbing process in the "Implementation details" section of my answer here.)

This syntax is better for spies:

doReturn(new ArrayList()).when(myClass).myList(any(), any());

Because this different when method receives an object, Mockito can prepare the object to do nothing during the stubbing, which avoids any spurious calls to your myList method.

Community
  • 1
  • 1
Jeff Bowman
  • 90,959
  • 16
  • 217
  • 251
0

Although Jeff's answer did not show a workaround for my problem it pointed me into the right direction.

After changing the mocking behaviour to doReturn... I suddenly got an error message. This message told me that myClass is not a mock which makes sense since you can only mock (or stub?) methods of mocked or spied objects. So as Jeff's answer indicates and is explained in the documentation of mockito I created a partial mock of MyClass with

MyClass myClass = Mockito.spy(new MyClass());

With this partial mock Jeff's approach to method mocking suddenly worked (mine still does not and should therefore be avoided).

So: Thank you, Jeff!

Bastian
  • 4,638
  • 6
  • 36
  • 55