Problem running example from Akka Geting Started Guide (iot example) Test

The part of the test suite for “DeviceGroup” looks like:

  probe.watch(toShutDown)
   toShutDown ! PoisonPill
   probe.expectTerminated(toShutDown)
 
   // using awaitAssert to retry because it might take longer for the groupActor
   // to see the Terminated, that order is undefined
   probe.awaitAssert {
     groupActor.tell(DeviceGroup.RequestDeviceList(requestId = 1), probe.ref)
     probe.expectMsg(DeviceGroup.ReplyDeviceList(requestId = 1, Set("device2")))
   }

The def Receive for DeviceGroup inlucdes

    case Terminated(deviceActor) ⇒
       val deviceId = actorToDeviceId(deviceActor)
       log.info("Device actor for {} has been terminated", deviceId)
       actorToDeviceId -= deviceActor
       deviceIdToActor -= deviceId

What’s weird is that the probe.expectTerminated(toShutdown) is passing
but:

  1. I’m not seeing the log message “Device … has been terminated”
  2. The last test that verifies that the Device has been removed from the DeviceGroup fails.

Has anyone else run into this? Suggestions on how to debug?

Hi David,

How are you running that spec, have you copied it to a project based on the akka-quickstart-scala or are you running it in some other way?

The log is at info level, have you set the akka.loglevel setting to info or debug and also made sure the logger used is not filtering INFO level logs out?

Thanks for responding Johan.
I’ve just copied the sources from the doc into an intellij project. Everything seems to be working fine except for this particular test (sending a PoisonPill to a DeviceActor and handling the Terminate message in the DeviceGroup.)

When I looked at the sources on Github I notice that the declaration of the test class extends “AkkaSpec”

import akka.actor.PoisonPill
import akka.testkit.{AkkaSpec, TestProbe}

import scala.concurrent.duration._

class DeviceGroupSpec extends AkkaSpec {

I tried adding this to my DeviceGroupSpec but intellij can’t find AkkaSpec.
I’m using build.sbt from AkkaQuickStart:

version := “1.0”

scalaVersion := “2.12.6”

lazy val akkaVersion = “2.5.21”

libraryDependencies ++= Seq(
“com.typesafe.akka” %% “akka-actor” % akkaVersion,
“com.typesafe.akka” %% “akka-testkit” % akkaVersion,
“org.scalatest” %% “scalatest” % “3.0.5” % “test”
)

Could this be the problem and if where do I find AkkaSpec?

Thanks again for your help!

I think I see the problem. I misinterpreted “expectTerminated” to mean that a “Terminate” message was received from the watched Actor. It just means that the Actor terminated. So somehow the DeviceGroup actor needs to be informed that the DeviceActor terminated via a Terminate message or some other mechanism that I don’t know about so that it can remove the Device Actor from its collection. Does this seem correct and if so how should I modify the Device or the DeviceGroup code?

Thanks again.

Problem solved! I have the DeviceGroup Actor watch newly created Device Actors so that it will receive the Terminate message and remove the dead actor. (I think the example needs to be modified to do this.)

There’s one other mystery in the test code having to do with “TestProbe” that’s bothering me. In the tests for DeviceGroupQuery we have the following:

val requester = TestProbe()

  val device1 = TestProbe()
  val device2 = TestProbe()

What is TestProbe() returning? requester is supposed to be a DeviceGroup actor and device 1 and 2 represent device actors but where how does the type of the actor get specified or am I completely missing something here. (This may be related to my previous question.)

Sorry, I found documentation on TestProbe

As far as I can see the device group is watching of it’s children:

https://doc.akka.io/docs/akka/current/guide/tutorial_4.html#keeping-track-of-the-device-actors-in-the-group

Maybe you are looking at the section before that is introduced?

You’re right! I missed that addition. Sorry!