2012-11-13 86 views
16

给定一个Java类两种方法(从的Mockito拍摄):部队单个参数可变参数

OngoingStubbing<T> thenReturn(T value); 

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

如果我从斯卡拉调用与

....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) 

而我无法弄清楚如何解决这个问题。

回答

12

这些答案都是错误的问题。区别很微妙,但这与linked ticket中的问题不是同一个问题。那个确实需要不合理的体操来称呼非可变参与者方法。对于这一个,以下就足够了。

thenReturn[String]("something") 

或者,如果您因为某种原因不想这样做,则不需要类型别名和演员表。您可以直接使用结构类型归属。

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

这里的问题是,在重载和多态性的交集类型推断 - 一种方法是更具体的,但scalac不弄清楚哪些。由于重载和元组转换之间的交互作用,SI-2991中的问题是真正的模糊性 - 两者都不是特定的。

+1

问题是,当你对一个返回java.lang.Object(又名AnyRef)的方法进行stubbing,然后你被Scala搞砸了。 –

+0

我认为你的意思是AnyVal不是一个对象 –

1

解决方法是相当简单:

OngoingStubbing<T> thenReturn(T value); 

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

没有“可变参数必须非空”的特点。

+0

我无法更改底层库。示例方法取自mockito。 – monkjack

+0

哟可以包装底层库或总是调用第二种方法。正如Alexey在其他答案中所解释的那样。 – Nicolas

9

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

thenReturn("something", Nil: _*) 

不能想办法要调用的方法不正确,现在可变参数。

+0

这对我来说适用于我的情况doReturn(false,Nil:_ *)允许我通过第二个elipsis参数 –

16

这是一个已知的Scala-Java互操作性问题,但不幸的是它不在FAQ中。这里是Scala ticket describing the problem。实质上,这两种方法都适用于您提供单一参数的情况,并且Scala编译器目前没有任何启发式方法来决定哪一个“更具体”。 Alexey Romanov's approach to always use the varargs version是一个很好的解决方法:

thenReturn("something", Nil: _*) 

还有一个question running into a similar problem with JCommander。其中一个答案提供了一个聪明的解决方法,使用结构类型。这种方法将在幕后使用反射,所以你可能会也可能不想去那个方向。对于你的用例,它看起来像这样:

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

最后,有一个similar question running into a similar problem with mokito。它并没有提供任何解决方法,但是如果您对发生这种情况的原因感兴趣,它可以更详细地描述问题。

+0

的AnyRef要求它的一切正常,直到您的返回是一个AnyVal(它不会转换为java对象) –

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]: _*) 
0

假设其他人会发现具有当这个问题overloaded method value thenReturn with alternatives错误,我想分享我的解决方案。

而不是

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

我用

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

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