4

Given the following code that mocks a Scala class with Mockito, I get an error and cannot compile:

import org.mockito.Mockito._

class Testeable {
  def fun1 = 1
  def fun2 = 2
}

object test {

  def getMock = {
      val testMock = mock[Testeable]  // <-- this line throws the error
      when(testMock.fun1).thenReturn(3)
      testMock
  }

}

Error is:

ambiguous reference to overloaded definition, both method mock in object Mockito of type (x$1: Class[common.Testeable], x$2: org.mockito.MockSettings)common.Testeable and method mock in object Mockito of type (x$1: Class[common.Testeable], x$2: org.mockito.stubbing.Answer[_])common.Testeable match expected type ?

I just mocked a class, what's ambiguous?

ps0604
  • 1,227
  • 23
  • 133
  • 330
  • `mock(classOf[Testeable])`? It expects a `java.lang.Class`, and `classOf` method provides it, just like in Java you could do `Testeable.class`. – insan-e Dec 27 '16 at 09:08
  • Correction, class `Any` has a `getClass` method, so for non-generic classes like `Int`, `String` etc you could use `getClass` and for generic ones like `List[T]` you use `classOf[List[_]]` from `Predef`... – insan-e Dec 27 '16 at 09:33
  • thanks, it worked using `mock(classOf[Testeable])` – ps0604 Dec 27 '16 at 11:34
  • 1
    @insan-e mocking an `Int` sounds like a wonderful idea! :) – Dima Dec 27 '16 at 12:29

1 Answers1

4

You can't use mockito directly like this (you can use it, but can't make it look this pretty). Take a look at scala test library. The simplest thinng you can do to solve your immediate problem with it is just mix in MockitoSugar into your test class instead of importing Mockito._, then mock[Foo] will just work as you expect it to. There are many other things that library offers to write idiomatic test code in scala, so you should read through some docs and examples on that site I linked to.

Dima
  • 39,570
  • 6
  • 44
  • 70
  • 2
    using `mock(classOf[Testeable])` seems to work. Thoughts? – ps0604 Dec 27 '16 at 11:34
  • There are different overloaded flavors of `mock` in `Mockito`. The parametrized one you had before needs two arguments. The one that takes a single `Class` argument works with the latter syntax. Not sure what's throwing you off about it. – Dima Dec 27 '16 at 12:27
  • the gotcha is that scala doesn't handle signatures with elipsis well and it can't discern between the two. This is a bigger issue with the spy / doReturn returning an AnyVal scenario – Andrew Norman Sep 29 '17 at 00:38
  • @AndrewNorman no, this has nothing to do with ellipsis. Also, scala handles it just fine. – Dima Sep 29 '17 at 12:04
  • 1
    @Dima the scala elipsis issue is easily recognized in the following snippet: val myBool = false class MyClass(){ def booleanTest(): Boolean = {false} } val mySpy = spy(new MyClass) doReturn(myBool).when(mySpy).booleanTest compile error: ambiguous reference to overloaded definition, both method doReturn in object Mockito of type (x$1: Any, x$2: Object*)org.mockito.stubbing.Stubber and method doReturn in object Mockito of type (x$1: Any)org.mockito.stubbing.Stubber match argument types (Boolean) – Andrew Norman Oct 31 '17 at 22:34
  • @Dima - that is essentially the issue with scala not being able to handle method overloads w varargs / elipsis. This issue has been thoroughly discussed here: https://stackoverflow.com/questions/6209120/scala-ambiguous-reference-to-overloaded-definition-with-varargs – Andrew Norman Oct 31 '17 at 22:37
  • @AndrewNorman that's a different issue. This one has nothing to do with elipsis. THAT one does. Thus the difference. Also, in your snippet, both method definitions DO match your invocation. So, that's an issue with your code, not with scala :) – Dima Nov 01 '17 at 12:47
  • @Dima if I'm passing one parameter, its obviously the former one parameter doReturn definition and not the later doReturn with the second varg parameter that I'm using. Anyone trying to use the single parameter doReturn definition will have the ambiguous reference issue in scala. Thats not a code issue other than scala, itself can't figure out the ambiguity in this java mock library. This problem becomes a block if what you want to return is an AnyVal and not an AnyRef as the vararg overload only supports AnyRef objects. – Andrew Norman Nov 01 '17 at 19:30
  • I am just saying that OP's question (and my answer) has nothing to do with the ellipsis issue whatsoever. As for your "issue" with `doReturn`, I am not sure which version of Mockito you are using. The one I am looking at (1.10.14) does not have overloads for `doReturn` (and compiles your example fine). There is a varargs override for `thenReturn`, but that also compiles fine, for both single-argument, and varargs version (yes you can use varargs with AnyVal - there's autoboxing for that). Once again though: none of this has anything to do with the original question. – Dima Nov 01 '17 at 22:52
  • @Dima The link you gave does not have section about how to solve this ambiguity problem, do you have other links? Thanks. – BlueDolphin Jul 04 '18 at 04:40
  • @BlueDolphin, I explained it in my answer: just mix in `MockitoSugar` instead of imoorting `Mockito.mock` – Dima Jul 08 '18 at 16:50