18

给定一个具有两种方法的 java 类(取自 mockito):

OngoingStubbing<T> thenReturn(T value);

OngoingStubbing<T> thenReturn(T value, T... values);

如果我从 scala 调用

....thenReturn("something")

我收到一个错误:

Description Resource    Path    Location    Type
ambiguous reference to overloaded definition, both method thenReturn in trait OngoingStubbing of type (x$1: java.lang.Object, x$2: <repeated...>[java.lang.Object])org.mockito.stubbing.OngoingStubbing[java.lang.Object] and  method thenReturn in trait OngoingStubbing of type (x$1: java.lang.Object)org.mockito.stubbing.OngoingStubbing[java.lang.Object] match argument types (java.lang.String)

我不知道如何解决这个问题。

4

6 回答 6

23

这是一个已知的 Scala-Java 互操作性问题,尽管很遗憾不在 FAQ 中。这是描述问题的 Scala 票证。本质上,当您给出单个参数时,这两种方法都适用,并且 Scala 编译器目前没有任何启发式方法来确定哪个“更具体”。Alexey Romanov 始终使用可变参数版本的方法是一个很好的解决方法:

thenReturn("something", Nil: _*)

还有一个问题遇到了与 JCommander 类似的问题。那里的答案之一提供了使用结构类型的巧妙解决方法。这种方法将在幕后使用反射,所以你可能想也可能不想去那个方向。对于您的用例,它看起来像:

type useSingleArgVersion = { def thenReturn(value: AnyRef): OngoingStubbing }
(...).asInstanceOf[useSingleArgVersion].thenReturn("something")

最后,有一个类似的问题遇到了 mokito 的类似问题。它并没有真正提供任何解决方法,但它确实更详细地描述了问题,如果您对发生这种情况的原因感兴趣的话。

于 2012-11-13T13:27:03.583 回答
14

如果调用可变参数版本是可以接受的,

thenReturn("something", Nil: _*)

现在想不出一种方法来调用没有可变参数的方法。

于 2012-11-13T10:10:42.153 回答
13

这些答案都是错误的问题。差异是微妙的,但这与链接票证中的问题不同。那确实需要不合理的体操来调用非可变参数方法。对于这一点,以下就足够了。

thenReturn[String]("something")

或者,如果您出于某种原因不想这样做,则不需要类型别名和强制转换。您可以直接使用结构类型归属。

(this: { def thenReturn[T](s: T): OngoingStubbing[T] }).thenReturn("something")

这里的问题是重载和多态交叉处的类型推断——一种方法更具体,但 scalac 不知道是哪一种。由于重载和元组转换之间的相互作用,SI-2991 中的问题是真正的歧义——两者都不是更具体的。

于 2013-01-12T06:05:14.377 回答
2

假设其他人在遇到overloaded method value thenReturn with alternatives错误时会发现这个问题,我也想分享我的解决方案。

代替

when(field.getValue(isA(classOf[Record]))).thenReturn(value)

我用

doReturn(value).when(field).getValue(isA(classOf[Record]))

这解决了我的情况的歧义。

于 2017-11-30T10:22:38.293 回答
1

解决方法很简单:

OngoingStubbing<T> thenReturn(T value);

OngoingStubbing<T> thenReturn(T value1, T valu2, T... values);

没有“可变参数必须为非空”功能。

于 2012-11-13T10:08:54.807 回答
0

我尝试了史蒂夫的解决方案并得到了一个巨大的编译器错误,包括:

scala.tools.nsc.symtab.Types$TypeError: type mismatch;
 found   : scala.reflect.Manifest[Nothing]
 required: scala.reflect.ClassManifest[B]
Note: Nothing <: B, but trait ClassManifest is invariant in type T.
You may wish to investigate a wildcard type such as `_ <: B`. (SLS 3.2.10)

我能够使它与类似的东西一起工作:

thenReturn("something", Seq.empty[Object]: _*)
于 2014-01-28T18:35:54.623 回答