2013-05-12 7 views
12

У меня немного трудное время, пытаясь понять, как писать тесты в Scala, когда задействованы неявные параметры.Scala тестирует насмешливые неявные параметры?

У меня есть следующий (короткая версия) моего кода и тестирования:

реализации (Scala 2,10, спрей и Акка):

import spray.httpx.SprayJsonSupport._ 
import com.acme.ResultJsonFormat._ 

case class PerRequestIndexingActor(ctx: RequestContext) extends Actor with ActorLogging { 
    def receive = LoggingReceive { 
    case AddToIndexRequestCompleted(result) => 
     ctx.complete(result) 
     context.stop(self) 
    } 
} 


object ResultJsonFormat extends DefaultJsonProtocol { 
    implicit val resultFormat = jsonFormat2(Result) 
} 

case class Result(code: Int, message: String) 

Test (Использование ScalaTest и Mockito):

"Per Request Indexing Actor" should { 
    "send the HTTP Response when AddToIndexRequestCompleted message is received" in { 
     val request = mock[RequestContext] 
     val result = mock[Result] 

     val perRequestIndexingActor = TestActorRef(Props(new PerRequestIndexingActor(request))) 
     perRequestIndexingActor ! AddToIndexRequestCompleted(result) 

     verify(request).complete(result) 
    } 
    } 

Эта строка, verify(request).complete(result) использует неявный маршаллер, чтобы превратить Result в JSON.

Я могу привести маршаллера в область видимости, добавив implicit val marshaller: Marshaller[Result] = mock[Marshaller[Result]], но когда я запускаю тест, используется другой экземпляр Marshaller, поэтому проверка не выполняется.

Даже явно пропуская макет Маршаллера до complete не удается.

Итак, может ли кто-нибудь посоветовать создать макет объекта для неявного параметра и убедиться, что экземпляр используется?

+0

Как явно пропустить неудачу? Почему вы хотите использовать макет маршаллера в первую очередь? (Я не использовал mockito, поэтому, пожалуйста, извините меня, если это глупые вопросы) – jrudolph

ответ

5

Это идеальная ситуация для использования Matcher от Mockito для marshaller arg. Вам не нужно будет издеваться над неявным маршаллером. Все, что вы действительно хотите сделать, это проверить, что complete был вызван с помощью result, соответствующего тому, что вы ожидали, а также некоторому экземпляру маршаллера. Во-первых, если вы еще не сделали это, принести Mockito matchers в сферу с импортом, так как:

import org.mockito.Matchers._ 

Затем, если вы хотите эталонную на результат, можно проверить следующим образом:

verify(request).complete(same(result))(any[classOf[Marshaller[Result]]]) 

Или, если вы хотите, равно согласование на результат вы можете сделать:

verify(request).complete(eq(result))(any(classOf[Marshaller[Result]])) 

трюк с matchers, что как только вы используете один на один арг, вы должны использовать их для всех аргументах, так вот почему мы имеем t o использовать один для result тоже.

+0

Я тоже это пробовал. Хотя я не пробовал использовать 'same()' matcher. Я не уверен, почему (пока) тест проходит при использовании 'verify (request) .complete (тот же (результат)) (любой [classOf [Marshaller [Result]]]), но не проходит при использовании' verify (request) .complete (экв (результат)) (любой (classOf [маршаллер [результат]])) '. Спасибо за ваше предложение, хотя это помогло :) – C0deAttack

+0

Поскольку переменная запроса сама по себе является макетом, а в eq-матчи используется метод equals, который не был заштрихован, вы всегда получаете false, поэтому не сопоставляетесь. То же самое хорошо подходит здесь. Если запрос не был издевательством, а вместо этого, класс case, eq мог бы поместиться лучше – cmbaxter

+1

Спасибо за продолжение. Извинения за неясность. Использование 'eq' теста даже не компилируется. Когда я использую 'eq', сообщение об ошибке« Тип несоответствие, ожидается: Marshaller [Boolean], actual: Marshaller [Result] ». И это ошибка на 'any (classOf [Marshaller [Result]]). Я не на 100% понимаю, почему возникает ошибка? Это довольно странно. – C0deAttack