Search code examples
javaeclipsemockitooverload-resolutionecj

Mockito: Verifying overloaded methods with type-compatible arguments


Consider you want to mock an interface using Mockito containing the following method signatures:

public void doThis(Object o);

public void doThis(Object... o)

I need to verify that doThis(Object o) (and not the other method) has been invoked exactly one time.

First I thought that the following line would do the trick:

verify(mock, times(1)).doThis(anyObject());

However, as this seems to work on Windows, it doesn't on Linux because in this environment, a call to of the other doThis method is expected.
This is caused because the anyObject() argument seems to match both method signatures and one is chosen in a more or less unpredictable way.

How can I enforce that Mockito always chooses doThis(Object o) for verification?


Solution

  • This is not a mockito issue.

    During further investigating, I realized that the actual method is chosen at compile-time (JLS §15.12.2). So basically the class files differed between windows and linux which caused different mockito behavior.

    The interface is discouraged (see Effective Java, 2nd Edition, Item 42). I changed it to match the following:

    public void doThis(Object o);
    
    public void doThis(Object firstObj, Object... others)
    

    With this change the expected (first) method will always be chosen.

    One thing is still left:
    Why does the java compiler on windows (eclipse compiler) produce a different output than Oracle JDK javac on Linux?

    This might be a bug in ECJ because I would expect that the java language spec is pretty strict here.