Can anyone explain the compile error below? Interestingly, if I change the return type of the get() method to String, the code compiles just fine. Note that the thenReturn method has two overloads: a unary method and a varargs method that takes at least one argument. It seems to me that if the invocation is ambiguous here, then it would always be ambiguous.
More importantly, is there any way to resolve the ambiguity?
import org.scalatest.mock.MockitoSugar
import org.mockito.Mockito._
trait Thing {
def get(): java.lang.Object
}
new MockitoSugar {
val t = mock[Thing]
when(t.get()).thenReturn("a")
}
error: ambiguous reference to overloaded definition,
both method thenReturn in trait OngoingStubbing of type
java.lang.Object,java.lang.Object*)org.mockito.stubbing.OngoingStubbing[java.lang.Object]
and method thenReturn in trait OngoingStubbing of type
(java.lang.Object)org.mockito.stubbing.OngoingStubbing[java.lang.Object]
match argument types (java.lang.String)
when(t.get()).thenReturn(“a”)
Well, it is ambiguous. I suppose Java semantics allow for it, and it might merit a ticket asking for Java semantics to be applied in Scala.
The source of the ambiguitity is this: a vararg parameter may receive any number of arguments, including 0. So, when you write
thenReturn("a"), do you mean to call thethenReturnwhich receives a single argument, or do you mean to call thethenReturnthat receives one object plus a vararg, passing 0 arguments to the vararg?Now, what this kind of thing happens, Scala tries to find which method is “more specific”. Anyone interested in the details should look up that in Scala’s specification, but here is the explanation of what happens in this particular case:
As to the “tuple conversion” thing, it is one of the most obscure syntactic sugars of Scala. If you make a call
f(a, b), whereaandbhave typesAandB, and there is nofaccepting(A, B)but there is anfwhich accepts(Tuple2(A, B)), then the parameters(a, b)will be converted into a tuple.For example:
Now, there is no tuple conversion going on when
thenReturn("a")is called. That is not the problem. The problem is that, given that tuple conversion is possible, neither version ofthenReturnis more specific, because any parameter passed to one could be passed to the other as well.