web-dev-qa-db-fra.com

Mockito Matchers, Scala Value Class et NullPointerException

J'utilise mockito avec scalatest. J'ai le problème suivant lors de l'utilisation de Matcher avec la classe de valeur.

import org.scalatest.FlatSpec
import org.scalatest.mock.MockitoSugar
import org.mockito.BDDMockito._
import org.mockito.Matchers.any

case class FirstId(val value: String) extends AnyVal
case class SecondId(val value: String) extends AnyVal

trait MockedClass {
  def someMethods(firstId: FirstId, secondId: SecondId): Int
}

class ValueClassSpec() extends FlatSpec with MockitoSugar {

  val mockedClass = mock[MockedClass]
  val secondId = SecondId("secondId")

  "Matchers" should "work for value class" in {
    // given
    given(mockedClass.someMethods(any[FirstId], org.mockito.Matchers.eq(secondId))).willReturn(3)
    // when
    val result = mockedClass.someMethods(FirstId("firstId"), secondId)
    // then
    assert(result == 3)
  }

}

et le résultat est:

ValueClassSpec:
Matchers
- should work for value class *** FAILED ***
  Java.lang.NullPointerException:
  at io.scalac.fow.party.ValueClassSpec$$anonfun$1.apply$mcV$sp(ValueClassSpec.scala:22)
  at io.scalac.fow.party.ValueClassSpec$$anonfun$1.apply(ValueClassSpec.scala:20)
  at io.scalac.fow.party.ValueClassSpec$$anonfun$1.apply(ValueClassSpec.scala:20)
  at org.scalatest.Transformer$$anonfun$apply$1.apply(Transformer.scala:22)
  at org.scalatest.Transformer$$anonfun$apply$1.apply(Transformer.scala:22)
  at org.scalatest.OutcomeOf$class.outcomeOf(OutcomeOf.scala:85)
  at org.scalatest.OutcomeOf$.outcomeOf(OutcomeOf.scala:104)
  at org.scalatest.Transformer.apply(Transformer.scala:22)
  at org.scalatest.Transformer.apply(Transformer.scala:20)
  at org.scalatest.FlatSpecLike$$anon$1.apply(FlatSpecLike.scala:1639)
  ...

J'ai trouvé une question similaire ( Les classes Scala Value et Mockito Matchers ne jouent pas ensemble ) mais sans aucun conseil.

Est-il possible d’utiliser des correspondants Mockito avec une classe de valeur scala?

Versions Lib: scala 2.11.2, mockito 1.10.8, scalatest 2.1.6

20
Marek Kliś

La solution appropriée est:

case class StringValue(val text: String) extends AnyVal
case class LongValue(val value: Long) extends AnyVal

val eqFirst: StringValue = StringValue(org.mockito.Matchers.eq("first"))
val anySecond: StringValue = StringValue(org.mockito.Matchers.any[String])

val eqFirst: LongValue = LongValue(org.mockito.Matchers.eq(1L))
val anySecond: LongValue = LongValue(org.mockito.Matchers.any[Long])
22
Marek Kliś

J'ai trouvé la solution:

val anyFirstId: FirstId = any[String].asInstanceOf[FirstId]
val eqSecondId: SecondId = org.mockito.Matchers.eq[String](secondId.value).asInstanceOf[SecondId]
given(mockedClass.someMethods(anyFirstId, eqSecondId)).willReturn(3)
9
Marek Kliś

Cela fonctionne pour tous les types de classes de valeur extends AnyVal et n'a pas besoin d'appariants spéciaux non plus:

    given(mockedClass.someMethods(FirstId(anyString), SecondId(org.mockito.Matchers.eq(secondId.value)))).willReturn(3)
3
mr MR

La version la plus récente de mockito-scala (0.0.9) prend en charge cette option, vous pouvez faire quelque chose comme:

when(myObj.myMethod(anyVal[MyValueClass]) thenReturn "something"

myObj.myMethod(MyValueClass(456)) shouldBe "something"

verify(myObj).myMethod(eqToVal[MyValueClass](456))

Avertissement: je suis développeur de cette bibliothèque

1
Bruno