2012-11-13 25 views
16

Cho một lớp java với hai phương pháp (lấy từ Mockito):Force đối số duy nhất trong scala varargs

OngoingStubbing<T> thenReturn(T value); 

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

Nếu tôi gọi từ scala với

....thenReturn("something") 

tôi nhận được một lỗi:

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) 

Và tôi không thể tìm ra cách khắc phục điều này.

Trả lời

12

Những câu trả lời này là tất cả cho câu hỏi sai. Sự khác biệt là tinh tế, nhưng đây không phải là vấn đề tương tự như vấn đề trong số linked ticket. Đó là một trong những yêu cầu thể dục không hợp lý để gọi phương pháp không varargs. Đối với điều này, sau đây là đủ.

thenReturn[String]("something") 

Hoặc, nếu bạn không muốn làm điều đó vì lý do nào đó, bạn không cần bí danh loại và dàn diễn viên. Bạn có thể sử dụng trực tiếp một kiểu cấu trúc.

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

Vấn đề ở đây là suy luận kiểu tại giao điểm của quá tải và đa hình - một phương pháp cụ thể hơn, nhưng scalac không tìm ra cái nào. Vấn đề trong SI-2991 là sự mơ hồ chính hãng do sự tương tác giữa quá tải và chuyển đổi tuple - không cụ thể hơn.

+1

Vấn đề là khi bạn đang stubbing một phương pháp mà trả về java.lang.Object (aka AnyRef) và sau đó bạn đang screwed bởi Scala. –

+0

Tôi nghĩ bạn có nghĩa là AnyVal không phải là một đối tượng –

1

Cách giải quyết khá đơn giản:

OngoingStubbing<T> thenReturn(T value); 

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

Không có "varargs phải là không có sản phẩm nào" tính năng.

+0

Tôi không thể thay đổi thư viện cơ bản. Các phương pháp ví dụ được lấy từ mockito. – monkjack

+0

Yo có thể quấn thư viện cơ bản hoặc luôn gọi phương thức thứ hai. Theo giải thích của Alexey trong câu trả lời khác. – Nicolas

9

Nếu gọi phiên bản vararg là chấp nhận được,

thenReturn("something", Nil: _*) 

không thể nghĩ ra một cách để gọi phương thức mà không varargs ngay bây giờ.

+0

điều này làm việc cho tôi trong trường hợp của tôi doReturn (false, Nil: _ *) cho phép tôi vượt qua yêu cầu AnyRef của tham số elipsis thứ hai –

16

Đây là vấn đề về khả năng tương tác Scala-Java đã biết, mặc dù rất tiếc là không có trong Câu hỏi thường gặp. Đây là số Scala ticket describing the problem. Về cơ bản, cả hai phương pháp đều có thể áp dụng khi bạn đưa ra một đối số duy nhất, và trình biên dịch Scala hiện không có bất kỳ phương pháp heuristic nào để quyết định cái nào là "cụ thể hơn". Alexey Romanov's approach to always use the varargs version là giải pháp tốt:

thenReturn("something", Nil: _*) 

Ngoài ra còn có question running into a similar problem with JCommander. Một trong những câu trả lời có một cách giải quyết thông minh bằng cách sử dụng các kiểu cấu trúc. Cách tiếp cận này sẽ sử dụng sự phản chiếu đằng sau hậu trường, vì vậy bạn có thể hoặc không muốn đi theo hướng đó. Đối với trường hợp sử dụng của bạn, hình thức trông giống như sau:

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

Cuối cùng, có similar question running into a similar problem with mokito. Nó không thực sự cung cấp bất kỳ cách giải quyết nào, nhưng nó mô tả vấn đề chi tiết hơn một chút, nếu bạn quan tâm đến lý do điều này xảy ra.

+0

tất cả tiền phạt cho đến khi trở về của bạn là AnyVal (không dịch sang đối tượng java)) –

0

tôi đã cố gắng giải pháp của Steve và nhận được một lỗi biên dịch khổng lồ bao gồm:

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) 

tôi đã có thể làm cho nó làm việc với một cái gì đó như:

thenReturn("something", Seq.empty[Object]: _*) 
0

Giả sử những người khác sẽ tìm thấy câu hỏi này khi có overloaded method value thenReturn with alternatives lỗi, tôi cũng muốn chia sẻ giải pháp của mình.

Thay vì

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

tôi sử dụng

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

mà giải quyết các disambiguity trong trường hợp của tôi.

Các vấn đề liên quan