I need to mock a function from an arbitrary type to another type that is a value-class.
For example with the following signature String => ValueClass
.
This is how my value-class is implemented:
final case class ValueClass(value: String) extends AnyVal
I am using mockito-scala to mock and scalatest to matche result:
import org.mockito.{ArgumentMatchersSugar, MockitoSugar}
import org.scalatest.{Matchers, WordSpecLike}
class ValueClassMockTest
extends WordSpecLike
with MockitoSugar
with ArgumentMatchersSugar
with Matchers {
"mocked function" should {
"return the same value class" in {
val f: String => ValueClass = mock[String => ValueClass]
when(f(any[String])).thenReturn(ValueClass("str"))
f("anyStringValue") shouldEqual ValueClass("str")
}
}
}
I wondering, why this test doesn't pass and mocked function returns unwrapped value?
"str" did not equal ValueClass(str)
ScalaTestFailureLocation: services.ValueClassMockTest at (ValueClassMockTest.scala:16)
Expected :ValueClass(str)
Actual :"str"
<Click to see difference>
build.sbt
scalaVersion = "2.12.10"
scalaTest = "3.0.8"
mockitoScala = "1.5.17"
Fixed in v1.5.18 (https://github.com/mockito/mockito-scala/pull/152)
The issue comes from the fact that on a parametrised return type there is no type info in runtime, hence the value class is always boxed, I added extra provisions for those scenarios so the boxed instance is returned.
That said, for stuff like functions I think is a better idea to skip mocking altogether, unless the function is impure or you want to assert some unorthodox behaviour.