2013-05-12 12 views
12

Ich habe eine harte Zeit zu versuchen, zu verstehen, wie man Tests in Scala schreibt, wenn implizite Parameter beteiligt sind.Scala testet implizite implizite Parameter?

ich folgende (Kurzfassung) habe von meinem Code und Test:

Implementation (Scala 2.10, Spray und Akka):

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 (Mit ScalaTest und 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) 
    } 
    } 

Diese Zeile verify(request).complete(result) verwendet einen impliziten Marshaller, um Result in JSON umzuwandeln.

Ich kann einen Marshaller in den Geltungsbereich bringen, indem ich implicit val marshaller: Marshaller[Result] = mock[Marshaller[Result]] hinzufüge, aber wenn ich den Test ausführe, wird eine andere Instanz von Marshaller verwendet, so dass die Überprüfung fehlschlägt.

Selbst die explizite Weitergabe des Pseudo-Marshallers an complete schlägt fehl.

Also, kann jemand beraten, wie man ein Mock-Objekt für einen impliziten Parameter erstellen und sicherstellen, dass die Instanz verwendet wird?

+0

Wie funktioniert das explizite Übergeben des Mocks? Warum solltest du überhaupt einen Mocksalber benutzen? (Ich habe kein Mockito benutzt, also entschuldige bitte, wenn das dumme Fragen sind) – jrudolph

Antwort

5

Dies ist eine perfekte Situation, um eine Matcher von Mockito für den Marshaller arg zu verwenden. Sie sollten den impliziten Marshaller nicht verspotten müssen. Alles, was Sie wirklich tun möchten, ist zu verifizieren, dass complete mit einem result aufgerufen wurde, was zu dem, was Sie erwarteten, und auch einige Instanzen des Marshallers. Erstens, wenn Sie nicht bereits getan, bringt die Mockito Matcher in Rahmen mit einem Import in etwa so:

import org.mockito.Matchers._ 

Dann, wenn Sie Referenzanpassung auf dem Ergebnis wollen, könnten Sie wie so überprüfen:

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

Oder, wenn Sie gleich Matching auf Ergebnis wollte könnten Sie tun:

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

Der Trick mit Matcher ist, dass wenn Sie ein für eine arg verwenden, müssen Sie sie für alle args verwenden, so dass deshalb wir haben T o Verwenden Sie einen für result auch.

+0

Ich hatte das auch versucht. Obwohl ich nicht versucht hatte, den 'same()' Matcher zu verwenden. Ich bin mir nicht sicher, warum (noch) der Test bestanden hat, wenn 'verify (request) .complete (selbe (result)) (any [classOf [Marshaller [Result]]]) verwendet wurde, aber nicht bestanden wird, wenn' verify (request) .complete (eq (result)) (beliebig (classOf [Marshaller [Result]])). Danke für Ihren Vorschlag, aber es half :) – C0deAttack

+0

Da die Anfrage-Variable selbst ein Mock ist, und der eq-Matcher verwendet die equals-Methode, die nicht gestempelt wurde, erhalten Sie immer falsch also keine Übereinstimmung. Das Gleiche passt hier gut. Wenn Anfrage nicht ein Schein war und stattdessen eine Fallklasse, könnte eq besser passen – cmbaxter

+1

Danke für das Follow-up. Entschuldigung dafür, dass ich nicht klar bin. Mit 'eq' wird der Test nicht einmal kompiliert. Wenn ich 'eq' verwende, lautet die Fehlermeldung" Type mismatch, expected: Marshaller [Boolean], aktuell: Marshaller [Result] ". Und es ist ein Fehler bei 'any (classOf [Marshaller [Result]])'. Ich bin nicht 100% klar, warum der Fehler auftritt? Es ist ziemlich merkwürdig. – C0deAttack

Verwandte Themen