Mockito matchers, scala value class и NullPointerException
Я использую mockito с scalatest. У меня есть следующая проблема при использовании matcher с классом value.
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 Matchers не играют вместе), но без каких-либо советов.
Есть ли возможность использовать Mockito matchers с классом Scala value?
Версии Lib: scala 2.11.2, mockito 1.10.8, scalatest 2.1.65 ответов:
Правильное решение:
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])
Я нашел решение:
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)
Это работает для всех типов
extends AnyVal
классов значений и не требует специальных сопоставителей:given(mockedClass.someMethods(FirstId(anyString), SecondId(org.mockito.Matchers.eq(secondId.value)))).willReturn(3)
Если у вас есть бесформенные зависимости, вы можете рассмотреть мой маленький вспомогательный метод: https://gist.github.com/Fristi/bbc9d0e04557278f8d19976188a0b733
Вместо того, чтобы писать
UserId(is(context.userId.value))
Вы можете написать
isAnyVal(context.userId)
Что немного удобнее : -)
Самая новая версия
mockito-scala
(0.0.9) поддерживает это из коробки, вы можете сделать что-то вродеwhen(myObj.myMethod(anyVal[MyValueClass]) thenReturn "something" myObj.myMethod(MyValueClass(456)) shouldBe "something" verify(myObj).myMethod(eqToVal[MyValueClass](456))
Отказ от ответственности: я разработчик этой библиотеки