2016-08-04 89 views
4

我試圖讓測試探測器回覆一個確認,每當它收到任何消息。Akka演員測試:使用TestProbe自動回覆

我寫了下面的代碼在我的測試,但它不工作:

val chgtWriter = new TestProbe(system) { 

      def receive: Receive = { 

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

      } 

     } 

有沒有辦法做到這一點。實際上將消息發送到測試探針的actor肯定是在另一個線程上運行,而不是TestThread。您可以在下面看到當前製作的完整測試。

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) 

} 

}

的changeSetActor完全測試和工程。測試與ChangeWriter掛起。它在接收方法中永遠不會收到消息。

EDIT1(以下@Jakko雁)

Auto Pilots情況如下:

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 
    } 
}) 

儘管到目前爲止給出的所有解釋是這樣清楚,什麼是在混亂官方的例子是參考「testActor」。誰是testActor在這裏?在那一點上沒有該名稱的變量聲明。

回答

3

您可以使用Auto Pilots編寫測試探針的腳本。例如:

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 
    } 
}) 

在上面的例子中,我們建立了一個測試探針與自動消息處理程序,自動駕駛。探測器收到消息時自動觸發將自動觸發。在這個例子中,自動駕駛會打印一條消息並回復給發件人。

消息處理完成後,自動導航可以決定如何處理下一個傳入的消息。它可以設置不同的自動駕駛儀,重新使用現有的自動駕駛儀(TestActor.KeepRunning),或完全禁用自動駕駛儀(TestActor.NoAutoPilot)。在這個例子中,相同的自動駕駛儀將用於處理所有傳入的消息。

即使將自動駕駛儀連接到探頭,仍然可以照常使用測試探頭聲明。

官方文檔中的testActor指您正在編寫測試的演員。例如,在您的情況下,演員可能是ChangeSetActor,分配給值chgtActor。由於您真正想要做的就是從探針迴應發件人,所以測試探針自動駕駛員回覆發件人並且不在乎testActor就足夠了。

+0

增加了缺少'KeepRunning'和一些關於如何使用它的細節。 –

+0

我沒有足夠的代表評論原帖,所以我只是在這裏添加我的評論。 'target.tell(message,source)'幾乎等同於'target!消息「:都發送消息到'目標'。不同之處在於,你必須用'.tell()'明確地指定消息發送者,但是使用'!'發送者將被隱式拾取。如果您在演員內部調用'!',演員將被用作發送者。 –

+0

我已經從你的答案更新了問題。我想這裏的問題是爲什麼你使用發件人! ACK而不是testActor.tell(ACK,發送方)。我不知道變量testActor在原始示例中代表什麼。最重要的是它在哪裏定義。 – MaatDeamon