Reputation: 1551
I want to mock a method taking a callback in argument let's say:
methodToMock[T](callback: (String, String) => T)
With play 2.3, (specs2 version 2.3.8) I managed to do it with the method doAnswer
from mockito:
doAnswer({ invocation =>
val method = invocation.asInstanceOf[(String, String) => Any] // L.34
method(role, key)
}).when(myMock).methodToMock[Any](any)
But since play 2.4 (using special dependency specs2, version 2.4.2), the previous code won't work, telling me:
[Ljava.lang.Object; cannot be cast to scala.Function2 (MySpec.scala:34)
I don't really understand why mockito start using Java objects in my code, since I'm using the specs2 implementation and didn't find any documentation about modifications on doAnswer
, nor usage example of my use case.
Do you have any idea of what I did wrong and a way to solve this?
EDIT:
I wanted to show a simplified case, but that deleted the source of the problem... The real definition of the method also takes an implicit arguments list:
methodToMock[T](callback: (String, String) => T)(implicit value: String)
Which means that specs2 seems to return an array instead of a single element (its behaviour really changed between the two versions though).
The following code now works
doAnswer({ invocation =>
val firstArgList = invocation.asInstanceOf[Array[Object]](0)
val method = firstArgList.asInstanceOf[(String, String) => Any] // L.34
method(role, key)
}).when(myMock).methodToMock[Any](any)(any)
Upvotes: 1
Views: 1740
Reputation: 15557
Which version of specs2 are you using? With 3.6.5
(the latest) the following works fine
case class T() {
def methodToMock[A](callback: (String, String) => A) = 1
}
val m = mock[T]
doAnswer({ invocation =>
val method = invocation.asInstanceOf[(String, String) => Any] // L.34
method("role", "key")
}).when(m).methodToMock[Any](any)
m.methodToMock((s: Any, s2: Any) => s.toString.size + s2.toString.size) === 7
Upvotes: 1