2015-01-11 72 views
3

我有以下演員層次父 - >子 - >工人 那裏孩子的生活範圍很緊,請求 - 當請求完成童星應終止。我想驗證它是測試的一部分。我創建了StepParent作爲測試用途,因爲我想驗證給定請求的響應,該請求將msg轉發給testprobe。童星終止確認

class StepParent(child: Props, name: String, probe: ActorRef) extends Actor with ActorLogging { 
    context.watch(context.actorOf(props = child, name = name)) 

    override def receive: Actor.Receive = { 
    case msg: PersistImages => context.children.foreach(child => child.tell(msg, sender)) 
    case msg => 
     log.debug(s"Msg forwarded to probe $msg") 
     probe.tell(msg, sender) 
    } 
} 

我的測試看起來如下:

class ImagesControllerActorTest extends TestKit(ActorSystem("testsystem")) 
with WordSpecLike with MustMatchers with StopSystemAfterAll { 

    val id = "456" 

    "ControllerActor" must { 
    "distribute a work to dedicated dedicated workers and combine back results and then terminate" in { 

     val p = TestProbe() 
     val ica = system.actorOf(Props(classOf[StepParent], createActorWithMockedWorkers(id, p.ref), "ControllerActor", p.ref), "parent") 

     p.send(ica, PersistImages(Set(new URL("http://success"), new URL("http://fail")))) 

     p.expectMsgPF(2 seconds)(validMsgPersistImageActor) 
     p.expectMsgPF(2 seconds)(validMsgPersistImageActor) 

     p.expectMsg(2 seconds, ImagesProcessed(id, Set(new URI("file:/")))) 

     p.expectMsg(4 seconds, Terminated) 
    } 
    } 

我的測試,因爲預期消息的最後一次檢查的失敗:

assertion failed: timeout (4 seconds) during expectMsg while waiting for Terminated 
java.lang.AssertionError: assertion failed: timeout (4 seconds) during expectMsg while waiting for Terminated 
    at scala.Predef$.assert(Predef.scala:179) 
    at akka.testkit.TestKitBase$class.expectMsg_internal(TestKit.scala:338) 
... 

根據詳細的日誌終止味精是轉發,以及(按照最後一行)

2015-01-11 17:41:10,386 [WARN ] [testsystem-akka.actor.default-dispatcher-5] akka.tcp://[email protected]:2555/user/parent/ControllerActor - id: 456 image url: http://fail FAILED 
2015-01-11 17:41:10,386 [INFO ] [testsystem-akka.actor.default-dispatcher-5] akka.tcp://[email protected]:2555/user/parent/ControllerActor - id: 456 Processing completed with 1 downloded and 1 failed 
2015-01-11 17:41:10,387 [DEBUG] [testsystem-akka.actor.default-dispatcher-4] akka.tcp://[email protected]:2555/user/parent - Msg forwarded to probe ImagesProcessed(456,Set(file:/)) 
2015-01-11 17:41:10,392 [DEBUG] [testsystem-akka.actor.default-dispatcher-2] akka://testsystem/user/parent/ControllerActor/$b - stopped 
2015-01-11 17:41:10,394 [DEBUG] [testsystem-akka.actor.default-dispatcher-5] akka://testsystem/user/parent/ControllerActor - stopping 
2015-01-11 17:41:10,396 [INFO ] [testsystem-akka.actor.default-dispatcher-4] akka://testsystem/user/parent/ControllerActor/$b - Message [akka.dispatch.sysmsg.Terminate] from Actor[akka://testsystem/user/parent/ImagesControllerActor/$b#-426862126] to Actor[akka://testsystem/user/parent/ControllerActor/$b#-426862126] was not delivered. [1] dead letters encountered. This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'. 
2015-01-11 17:41:10,396 [INFO ] [testsystem-akka.actor.default-dispatcher-2] akka://testsystem/user/parent/ControllerActor/$a - Message [akka.dispatch.sysmsg.Terminate] from Actor[akka://testsystem/user/parent/ControllerActor/$a#1067345522] to Actor[akka://testsystem/user/parent/ControllerActor/$a#1067345522] was not delivered. [2] dead letters encountered. This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'. 
2015-01-11 17:41:10,398 [DEBUG] [testsystem-akka.actor.default-dispatcher-2] akka://testsystem/user/parent/ControllerActor - stopped 
2015-01-11 17:41:10,399 [DEBUG] [testsystem-akka.actor.default-dispatcher-16] akka://testsystem/user/parent/ControllerActor/$a - stopped 
2015-01-11 17:41:10,399 [DEBUG] [testsystem-akka.actor.default-dispatcher-5] akka://testsystem/user/parent - received AutoReceiveMessage Envelope(Terminated(Actor[akka://testsystem/user/parent/ControllerActor#-770422232]),Actor[akka://testsystem/user/parent/ControllerActor#-770422232]) 
**2015-01-11 17:41:10,400 [DEBUG] [testsystem-akka.actor.default-dispatcher-5] akka.tcp://[email protected]:2555/user/parent - Msg forwarded to probe Terminated(Actor[akka://testsystem/user/parent/ControllerActor#-770422232])** 
... 

我不明白爲什麼最後一次預期的Msm檢查在這裏不起作用,因爲消息像往常一樣轉發。有沒有特別處理自動收到的消息?

有人懇求能帶來一些脫落到這一點?

THX

UPDATE: 試圖解決該所建議的 - 除去包裝信封如下:

class StepParent(child: Props, name: String, probe: ActorRef) extends Actor with ActorLogging { 
    context.watch(context.actorOf(props = child, name = name)) 

    override def receive: Actor.Receive = { 
    case msg: PersistImages => context.children.foreach(child => child.tell(msg, sender)) 
    case mssg: Envelope => 
     log.debug(s"Envelope msg forwarded to probe $mssg") 
     probe.tell(mssg.message, sender) 
    case msg => 
     log.debug(s"Msg forwarded to probe $msg") 
     probe.tell(msg, sender) 
    } 
} 

2015-01-11 23:52:16,352 [DEBUG] [testsystem-akka.actor.default-dispatcher-4] akka://testsystem/user/parent/ControllerActor - stopping 
2015-01-11 23:52:16,354 [DEBUG] [testsystem-akka.actor.default-dispatcher-4] akka://testsystem/user/parent/ControllerActor - stopped 
2015-01-11 23:52:16,358 [DEBUG] [testsystem-akka.actor.default-dispatcher-16] akka.tcp://[email protected]:2555/user/parent - Msg forwarded to probe ImagesProcessed(456,Set(file:/)) 
2015-01-11 23:52:16,358 [DEBUG] [testsystem-akka.actor.default-dispatcher-16] akka://testsystem/user/parent - received AutoReceiveMessage Envelope(Terminated(Actor[akka://testsystem/user/parent/ControllerActor#-1965336139]),Actor[akka://testsystem/user/parent/ControllerActor#-1965336139]) 
2015-01-11 23:52:16,360 [DEBUG] [testsystem-akka.actor.default-dispatcher-16] akka.tcp://[email protected]:2555/user/parent - Msg forwarded to probe Terminated(Actor[akka://testsystem/user/parent/ControllerActor#-1965336139]) 
2015-01-11 23:52:16,365 [DEBUG] [testsystem-akka.actor.default-dispatcher-16] akka://testsystem/system/testActor2 - received AutoReceiveMessage Envelope(Terminated(Actor[akka://testsystem/user/parent/ControllerActor#-1965336139]),Actor[akka://testsystem/user/parent/ControllerActor#-1965336139]) 

它仍然失敗,似乎事情可疑的東西在這裏:

2015-01-11 23:52:16,360 [DEBUG] [testsystem-akka.actor.default-dispatcher-16] akka.tcp://[email protected]:2555/user/parent - Msg forwarded to probe Terminated(Actor[akka://testsystem/user/parent/ImagesControllerActor#-1965336139]) 

不是從正確的繼父母的消息,但不知何故被提取。

+0

我不確定在'context.children.foreach(child => child.tell(msg,sender))'中使用'sender'時總是處於範圍內。你可以嘗試在actor中爲它創建一個引用,例如:case msg:PersistImages => val current_sender = sender; context.children.foreach(child => child.tell(msg,current_sender))' – Ashalynd

+0

@Ashalynd好的建議,但這也沒有幫助。與以前的消息相比,更多地通過相同的路徑併成功發送。 – jaksky

回答

0

所提出的解決方案不幸的是不工作,即使我還相信,他們可以工作,並從自動接收記錄終止消息已通過唯一的方式,我得到這個東西工作是一種「醜陋」的解決方案,通過將終止消息翻譯成其他東西:

class StepParent(child: Props, name: String, probe: ActorRef) extends Actor with ActorLogging { 
    context.watch(context.actorOf(props = child, name = name)) 

    override def receive: Actor.Receive = { 
    case msg: PersistImages => context.children.foreach(child => child.tell(msg, sender)) 
    case msg: Terminated => 
     log.debug("Parent: Terminated recieved") 
     probe.tell("controller terminated",sender) 
    case msg => 
     log.debug(s"Msg forwarded to probe $msg") 
     probe.tell(msg, sender) 
    } 
} 

和斷言邏輯正常工作爲:

p.expectMsg(4 seconds,"controller terminated") 

不知道發生了什麼事情,因爲它似乎終止味精不能簡單地轉發,即使它顯然是收到。

0

StepParent實際上收到Terminated消息的Envelope

您可以從日誌中看到它:

2015-01-11 17:41:10,399 [DEBUG] [testsystem-akka.actor.default-dispatcher-5] akka://testsystem/user/parent - received AutoReceiveMessage Envelope(Terminated(Actor[akka://testsystem/user/parent/ControllerActor#-770422232]),Actor[akka://testsystem/user/parent/ControllerActor#-770422232]) 

然而,Envelope消息在日誌中,然後打印,如果它是一個Terminated,而事實並非如此。

該消息是一個Envelope爲了包含來自自動發送的消息的發件人元數據,即使在這種情況下,Terminated消息已經包含發件人信息。

因此,對於你的測試通過,你可以這樣做:

override def receive: Actor.Receive = { 
    case msg: PersistImages => context.children.foreach(child => child.tell(msg, sender)) 
    case msg: Envelope => 
    log.debug(s"Envelope msg forwarded to probe $msg") 
    probe.tell(msg.message, sender) 
    case msg => 
    log.debug(s"Msg forwarded to probe $msg") 
    probe.tell(msg, sender) 
} 
+0

似乎有些可疑的東西因爲去掉只是包裝對象而沒有幫助 – jaksky

0

您的終止說法是不正確的。由於它是目前編碼:

p.expectMsg(4 seconds, Terminated) 

你基本上是說,你期待的消息是Terminated類型本身,而不是Terminated案例類的一個實例。你應該斷言更改爲:

p.expectMsg(4 seconds, Terminated(refToBeTerminated)) 

或更好:

p.expectTerminated(refToBeTerminated, 4 seconds) 

其中refToBeTerminated是你期望被終止ActorRef。我不確定這是否是您唯一的問題,但這確實是一個問題。

編輯

當然,如果你在乎的是,你有什麼樣的Terminate那麼你有多種選擇來測試。你可以嘗試:

p.expectMsgType[Terminated](4 seconds) 

或:

p.expectMsgClass(4 seconds, classOf[Terminated]) 

甚至:

p.expectMsgPF(4 seconds){case t:Terminated => } 
+0

我希望這樣我可以避免需要將我沒有的兒童ActorRef固定,並且它不容易從外部觀察。我不是特別感興趣的終止 – jaksky

+0

的內容不幸的是,甚至那些我看到他們通過自動接收日誌 – jaksky