2016-08-04 44 views
4

Ich versuche, eine Testsonde zu erhalten, mit einer Bestätigung zu antworten, wenn es irgendeine Nachricht erhält.Akka Actor Test: Automatische Antwort mit einer TestProbe

Ich schrieb den folgenden Code in meinem Test, aber es funktioniert nicht:

val chgtWriter = new TestProbe(system) { 

      def receive: Receive = { 

      case m => println("receive messagereplying with ACK"); sender() ! ACK 

      } 

     } 

Gibt es eine Möglichkeit, das zu tun. Der Akteur, der die Nachricht tatsächlich an die Testsonde sendet, läuft definitiv auf einem anderen Thread als TestThread. Unten können Sie den vollständigen Test sehen, wie er derzeit erstellt wird.

feature("The changeSetActor periodically fetch new change set following a schedule") { 


scenario("A ChangeSetActor fetch new changeset from a Fetcher Actor that return a full and an empty ChangeSet"){ 


    Given("a ChangeSetActor with a schedule of fetching a message every 10 seconds, a ChangeFetcher and a ChangeWriter") 

    val chgtFetcher = TestProbe() 

    val chgtWriter = new TestProbe(system) { 

     def receive: Receive = { 

     case m => println("receive message {} replying with ACK"); sender() ! ACK 

     } 

    } 
    val fromTime = Instant.now().truncatedTo(ChronoUnit.SECONDS) 
    val chgtActor = system.actorOf(ChangeSetActor.props(chgtWriter.ref, chgtFetcher.ref, fromTime)) 

    When("all are started") 


    Then("The Change Fetcher should receive at least 3 messages from the ChangeSetActor within 40 seconds") 

    var changesetSNum = 1 

    val received = chgtFetcher.receiveWhile(40 seconds) { 

     case FetchNewChangeSet(m) => { 

     println(s"received: FetchNewChangeSet(${m}") 

     if (changesetSNum == 1) { 
      chgtFetcher.reply(NewChangeSet(changeSet1)) 
      changesetSNum += 1 
      } 
      else 
      chgtFetcher.reply(NoAvailableChangeSet) 
     } 

     } 

    received.size should be (3) 

} 

}

Der changeSetActor vollständig getestet und funktioniert. Der Test hängt mit dem ChangeWriter. Es empfängt nie eine Nachricht in der Empfangs-Methode.

EDIT1 (Nach @Jakko Anser)

Die Auto Pilots ist wie folgt:

val probe = TestProbe() 
probe.setAutoPilot(new TestActor.AutoPilot { 
    def run(sender: ActorRef, msg: Any): TestActor.AutoPilot = 
    msg match { 
     case "stop" ⇒ TestActor.NoAutoPilot 
     case x  ⇒ **testActor.tell(x, sender)**; TestActor.KeepRunning 
    } 
}) 

Obwohl die ganze Erklärung so weit nachgegeben klar ist, was in der verwirrend offizielles Beispiel ist die Referenz "testActor". Wer ist testActor hier? Zu diesem Zeitpunkt gibt es keine variable Deklaration dieses Namens.

Antwort

3

Sie können Ihre Testsonden unter Verwendung von Auto Pilots skripten. Zum Beispiel:

import akka.testkit._ 
val probe = TestProbe() 
probe.setAutoPilot(new TestActor.AutoPilot { 
    def run(sender: ActorRef, msg: Any): TestActor.AutoPilot = { 
    println("receive messagereplying with ACK") 
    sender ! ACK 
    TestActor.KeepRunning 
    } 
}) 

Im obigen Beispiel haben wir eine Testsonde mit einer automatischen Nachricht Handler, Auto-Piloten auf. Der Autopilot wird automatisch ausgelöst, wenn die Sonde eine Nachricht empfängt. In diesem Beispiel druckt der Autopilot eine Nachricht und antwortet dem Absender.

Nachdem eine Nachricht bearbeitet wurde, kann der Autopilot entscheiden, wie die nächste eingehende Nachricht behandelt wird. Es kann entweder einen anderen Autopiloten einrichten, den vorhandenen Autopiloten (TestActor.KeepRunning) wiederverwenden oder den Autopilot vollständig deaktivieren (TestActor.NoAutoPilot). In diesem Beispiel wird derselbe Autopilot für die Verarbeitung aller eingehenden Nachrichten verwendet.

Sie können die Testsondierungen weiterhin wie gewohnt verwenden, selbst wenn der Autopilot an der Sonde angebracht ist.

Die testActor in der offiziellen Dokumentation bezieht sich auf den Akteur, gegen den Sie Tests schreiben. Zum Beispiel könnte in Ihrem Fall der Aktor die ChangeSetActor zugewiesenen Wert chgtActor sein. Da alles, was Sie wirklich tun wollen, ist es, auf den Sender von Sonde zurück zu antworten, es ist genug für die Testsonde Autopilot, um zurück zum Absender und nicht kümmern sich um die testActor.

+0

Hinzugefügt fehlende 'KeepRunning' und einige Details, wie man es benutzt. –

+0

Ich habe nicht genug Rep, um den ursprünglichen Post zu kommentieren, also werde ich einfach meine Kommentare hier hinzufügen. 'target.tell (message, source)' ist fast gleichbedeutend mit 'target! Nachricht ": Beide senden eine Nachricht an' target'. Der Unterschied besteht darin, dass Sie den Absender der Nachricht explizit mit '.tell()' angeben müssen, aber mit '!' Wird der Absender implizit ausgewählt. Wenn Sie '!' In einem Akteur aufrufen, wird der Akteur als Absender verwendet. –

+0

Ich habe die Frage mit Update von Ihrer Antwort bearbeitet. Ich denke, die Frage ist hier, warum Sie Absender verwenden! ACK anstelle von testActor.tell (ACK, Absender).Ich weiß nicht, was die Variable testActor im ursprünglichen Beispiel darstellt. Am wichtigsten ist, wo es definiert ist. – MaatDeamon