Child actor

I have the following parent hierarchy: parent -> child -> worker where reaching the child's life is difficult to request - when the request is complete, the child actor should be terminated. This I wanted to test as part of the test. I created a StepParent for testing as I want to test the response for a given request, which forwards to msg on 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)
  }
}

      

My test looks like this:

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

      

My test fails due to the last validation of the pending message:

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

      

According to verbose protocol Forwarded msg is also forwarded (according to last line)

2015-01-11 17:41:10,386 [WARN ] [testsystem-akka.actor.default-dispatcher-5] akka.tcp://testsystem@127.0.0.1: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://testsystem@127.0.0.1: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://testsystem@127.0.0.1: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://testsystem@127.0.0.1:2555/user/parent - Msg forwarded to probe Terminated(Actor[akka://testsystem/user/parent/ControllerActor#-770422232])**
...

      

I really don't understand why the last expected check of Msg is not working here as the message is being sent as usual. Is there any special handling for auto-received messages?

Could someone ask for some kind of strait?

thank

UPDATE: Tried to solve this as suggested - remove the Envelope wrapper like this:

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://testsystem@127.0.0.1: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://testsystem@127.0.0.1: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])

      

It still fails and it looks like something fishy is going on here:

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

      

This is not a valid message from StepParent, but retrieved somehow.

+3


source to share


3 answers


Unfortunately not the suggested solution worked, although I was also sure that they might work and from the automatic log retrieval the completed message was communicated the only way I got it working was a kind of "ugly" solution translated by the translated terminal to something else:

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

      

And the assertion logic works fine like:



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

      

Not sure what is going on as it seems that Terminated msg cannot be simply redirected even though it was clearly received.

0


source


StepParent

actually gets the message Envelope

message Terminated

.

You can see this from the log:

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

      

However, the message is Envelope

then printed in your logs as if it were Terminated

, until it is.



This is a message Envelope

to contain the sender's metadata from the auto-sent message, although in this case the message Terminated

already contains information about the sender.

So to make your test pass you can do something like:

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


source


Your completion statement is incorrect. Since it is currently coded:

p.expectMsg(4 seconds, Terminated)

      

you are basically saying that you are expecting a message, which is a type Terminated

and not an instance of the case class Terminated

. You should change the statement as follows:

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

      

or better yet:

p.expectTerminated(refToBeTerminated, 4 seconds)

      

where refToBeTerminated

is this ActorRef

which you expect to terminate. I'm not sure if this is your only problem, but this is the problem.

EDIT

Of course, if all you care about is that you have some Terminate

, then you have several options to test that. You may try:

p.expectMsgType[Terminated](4 seconds)

      

or

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

      

or even:

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

      

0


source







All Articles