2014-12-04 3 views
16

Я использую mockito с scalatest. У меня возникает следующая проблема при использовании сопряжения с классом значений.Mockito matchers, scala value class и NullPointerException

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 classes and Mockito Matchers don't play together), но без каких-либо рекомендаций.

Есть ли возможность использовать mockito-сокеты с классом класса scala?

Lib версии: 2.11.2, Скала Mockito 1.10.8, scalatest 2.1.6

+0

afaik 'any' и' eq' не могут использоваться вместе. – Ashalynd

+0

@Ashalynd - из [Документация Mockito] (http://mockito.github.io/mockito/docs/current/org/mockito/Mockito.html): ** Предупреждение о совпадениях аргументов: ** Если вы используете согласования аргументов, все аргументы должны быть предоставлены помощниками. Пример: (пример показывает подтверждение, но то же самое относится и к обрезанию): проверить (mock) .someMethod (anyInt(), anyString(), eq («третий аргумент»)); // выше правильно - eq() также является совпадением аргументов –

ответ

19

Правильное решение является:

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]) 
+0

Когда я делаю это, я получаю кучу ошибок и предупреждений о не использовании matchers вне гася: вал anyProjectName = org.mockito.ArgumentMatchers.any [String] .asInstanceOf [ProjectName] org.mockito.exceptions. злоупотребляет.InvalidUseOfMatchersException: Обнаружен неправильный или несоответствующий аргумент аргумента: –

9

я нашел решение:

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) 
+0

Было бы здорово, если бы вы реализовали свой собственный набор для AnyVals и поместили его в GitHub. –

+0

Нелегко написать генератор eq для AnyVal. –

+0

Это сработало для вас? Я получаю исключение ClassCastException. –

1

это работает для всех видов классов стоимости extends AnyVal и не нуждается в специальных приспособлениях:

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

Если у вас есть бесформенный в своих зависимостей вы могли бы рассмотреть мой маленький вспомогательный метод: https://gist.github.com/Fristi/bbc9d0e04557278f8d19976188a0b733

Вместо того чтобы писать

UserId(is(context.userId.value))

Вы можете написать

isAnyVal(context.userId)

Что немного более удобно :-)

Смежные вопросы