web-dev-qa-db-ja.com

Mockitoマッチャー、scala値クラスおよびNullPointerException

私はmockitoをscalatestで使用しています。値クラスでマッチャーを使用すると、次の問題が発生します。

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)
  }

}

結果は次のとおりです。

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)
  ...

同様の質問( Scala ValueクラスとMockitoマッチャーは一緒にプレイしない )を見つけましたが、アドバイスはありませんでした。

scala value classでmockitoマッチャーを使用する可能性はありますか?

Libバージョン:scala 2.11.2、mockito 1.10.8、scalatest 2.1.6

22
Marek Kliś

適切なソリューションは次のとおりです。

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])
27
Marek Kliś

私は解決策を見つけました:

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ś

これはすべての種類のextends AnyVal値クラスで、特別なマッチャーも必要ありません。

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

mockito-scala(0.0.9)の最新バージョンは、これをそのまま使用できるので、次のようなことができます

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

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

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

免責事項:私はそのライブラリの開発者です

3
Bruno

依存関係に形がない場合は、私の小さなヘルパーメソッドを検討できます: https://Gist.github.com/Fristi/bbc9d0e04557278f8d19976188a0b7

書く代わりに

UserId(is(context.userId.value))

あなたは書ける

isAnyVal(context.userId)

もう少し便利です:-)

1
mark_dj