3

I'm trying to mock a method that returns an instance of a value class (extends AnyVal) I'm getting some weird error message, which I understand (because of value class erasure) but I'm surprised Mockito doesn't cope with that.

My class:

case class MyValueClass(value: String) extends AnyVal

The function I want to mock:

trait ToMock {
  def something(someParams: String): MyValueClass
}

And the mock:

val theMock = mock[ToMock]
val returned = MyValueClass("test")
when(theMock.something("test")).thenReturn(returned)

This code generates the following error:

MyValueClass cannot be returned by something()
something() should return String

But of course, if I make it return a String, it doesn't compile anymore...

If I remove extends AnyVal, of course it works fine.

Guillaume
  • 22,694
  • 14
  • 56
  • 70
  • 1
    Mockito gives "zip" about your Scala types. I would use javap to understand the *true* signature of that method by checking the content in the bytecode files first. To be really sure that your scala-perception matches the content that Mockito is using to make its decisions. – GhostCat May 18 '17 at 06:19
  • That's the problem: to compile, Scala needs MyValueClass, but of course because it's a value class, it's erased on byte code, so at runtime, mockito wants the wrapped value (a String in my example). I'm only looking for a workaround. – Guillaume May 18 '17 at 08:34
  • Found a way, see my answer below – Guillaume May 18 '17 at 09:28
  • Glad you found a solution. Good to remember that one can "cheat out" of such problems this way. – GhostCat May 18 '17 at 09:59

1 Answers1

2

OK, I found an answer that works. I need to use the older mockito style of doReturn

doReturn(returned.value).when(theMock).something("test")

Because it's not type-safe, it works. Not fully satisfactory though, as I give up type safety.

Guillaume
  • 22,694
  • 14
  • 56
  • 70