Issue 415 in mockito: overloaded methods with vararg variants cause problem

564 views
Skip to first unread message

moc...@googlecode.com

unread,
Jan 28, 2013, 11:14:29 AM1/28/13
to mocki...@googlegroups.com
Status: New
Owner: ----
Labels: Type-Defect Priority-Medium

New issue 415 by Attila.P...@gmail.com: overloaded methods with vararg
variants cause problem
http://code.google.com/p/mockito/issues/detail?id=415

<code>
package org.test.mockito;

import java.util.Collection;

import org.junit.Test;
import org.mockito.Mockito;

public class MockitoTest extends Mockito {
ToTest toTestMock = mock(ToTest.class);
GenericHelper<Collection> listMock = mock(GenericHelper.class);

class GenericHelper<T> {
T t;

T getT() {
return t;
}
}

class ToTest {
String mymethod(Object... os) {
return "Object array, size: " + os.length;
}

String mymethod(GenericHelper<?>... ts) {
return "GenericHelper array, size: " + ts.length;
}

String mymethod(GenericHelper<Collection<?>> gh) {
return "GenericHelper, value: " + gh.getT();
}

String mymethod(Collection<?> collection) {
return "collection, size: " + collection.size();
}

}

@Test
public void test() {
GenericHelper<Collection> castedWithGeneric = listMock;
//when(toTestMock.mymethod(any(GenericHelper.class))).thenReturn("
Mocked method called!"); // returns null
//when(toTestMock.mymethod(any())).thenReturn(" Mocked method
called!"); // returns null
when(toTestMock.mymethod(eq(castedWithGeneric))).thenReturn("
Mocked method called!"); //works
//when(toTestMock.mymethod(castedWithGeneric)).thenReturn(" Mocked
method called!"); //works
String s = toTestMock.mymethod(listMock);
System.out.println(s);
}

}
</code>
Above test code fails when the lines marked with null is commented in to
work.
The general problem is, that by mocking a class, that has several
overloaded methods, including some with varargs parameter, and in the above
generic structure, the type based argument matchers seems don't work.

Expected output would be the "Mocked method called" in all lines, but with
those remarked with null, null will return - method is not stubbed as it
should have.



What version of the product are you using? 1.8.4

On what operating system? Win7

I found the problem during JPA Criteria API mocking, the actual mocked
object was the ExpressionImpl object, the method is the in() method, that
has 4 overloaded variants, from which 2 uses vararg. Inside the Mockito
code InvocationMatcher.hasSameMethod showed, that while i was calling with
the Expression parameter method, the candidate's type was Expression[], and
this unmatch led to returning null. I will stay contact, and give
additional information as needed.

moc...@googlecode.com

unread,
Jan 29, 2013, 4:35:16 AM1/29/13
to mocki...@googlegroups.com

Comment #1 on issue 415 by brice.du...@gmail.com: overloaded methods with
Hi,

I'm not sure what your problem is, or if there's a real issue with Mockito
but here's the Java compiler sees things.

when(toTestMock.mymethod(any(GenericHelper.class))).thenReturn(" Mocked
method called!");
-> will be compiled to : INVOKEVIRTUAL MockitoTest$ToTest.mymethod
(LMockitoTest$GenericHelper;)Ljava/lang/String;

when(toTestMock.mymethod(any())).thenReturn(" Mocked method called!");
-> will be compiled to : INVOKEVIRTUAL MockitoTest$ToTest.mymethod
([Ljava/lang/Object;)Ljava/lang/String;

when(toTestMock.mymethod(eq(castedWithGeneric))).thenReturn(" Mocked method
called!");
-> will be compiled to : INVOKEVIRTUAL MockitoTest$ToTest.mymethod
([LMockitoTest$GenericHelper;)Ljava/lang/String;


However the line
toTestMock.mymethod(listMock)
-> will be compiled to : INVOKEVIRTUAL MockitoTest$ToTest.mymethod
([LMockitoTest$GenericHelper;)Ljava/lang/String;

Which is the same as the third stub. If your actual invocation gets
compiled to one of the other form it'll work as expected. Unfortunately we
don't really want to greedly stub overloaded declaration.

Also note that at the moment the javadoc of 'any' says it doesn't do any
type checks, it's a short version for 'anything'. Too bad many people
mistake that with isA. We will certainly change that later.

Hope that helps a bit.

moc...@googlecode.com

unread,
Jan 30, 2013, 6:01:48 AM1/30/13
to mocki...@googlegroups.com

Comment #2 on issue 415 by Attila.P...@gmail.com: overloaded methods with
I have consulted with a more experienced colleague here, and it turned out
that the issue is caused by how generic works in Java. It seems that this
problem is not related to Mockito.

this definition:
GenericHelper<Collection> castedWithGeneric = listMock;

does not match the intended method's parameter:
String mymethod(GenericHelper<Collection<?>> gh)

because GenericHelper<Collection<?>> does not extend
GenericHelper<Collection>
this relation is only true between the Collection - Collection<?>

so, the compiler picks up the next relevant method, the
String mymethod(GenericHelper<?>... ts)

Mockito assigns the stub to this method, which does not match the actual
call's parameter.

I should have defined the mocked object as:
GenericHelper<Collection<?>> castedWithGeneric = mock(GenericHelper.class);

moc...@googlecode.com

unread,
Jan 30, 2013, 6:18:11 AM1/30/13
to mocki...@googlegroups.com
Updates:
Status: Invalid

Comment #3 on issue 415 by brice.du...@gmail.com: overloaded methods with
OK, glad you overcame your problem.

Don't hesitate to go to the mailing list if you are unsure if this is a bug
with mockito ;)

Cheers
Brice

Reply all
Reply to author
Forward
0 new messages