2012-11-13 84 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]))

這解決了我的情況下歧義。