2015-01-11 28 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