0
votes

My app uses a Supervisor akka actor that internally initialized other actors (childs). However, as it does that asynchronously, I am experiencing issues when trying to write tests with Akka TestKit.

For example, when trying to test how a system is terminated from another system by sending a message to a child actor of the supervisor, I create a new actor system, and then with actorOf a supervisor which receives a configuracion (used to create the child actors inside the supervisor), like so:

val anotherSystem: ActorSystem = ActorSystem("anotherSystem")

anotherSystem.actorOf(Props(classOf[Supervisor], new ConfigurationFromStatic(configsAnother), metrics), "AnotherSupervisor")

Then if I try to send a message to a child actor within AnotherSupervisor using actorSelection it fails as the child actor is yet not selectable:

anotherSystem.actorSelection("/user/AnotherSupervisor/AnotherManagementReceiver") ! message
expectMsg(Ack)

Fails as there is no AnotherManagementReceiver created yet.

Using a Thread.sleep(5000) works, but that's just awful.

After searching for possible solutions, I tested:

anotherSystem.actorSelection("/user/AnotherSupervisor/AnotherManagementReceiver").resolveOne() ! message

Also fails with an existing actor message.

Also tried EventFilter to get something echoed in the log by the child actor:

EventFilter.info("Management consumer started", occurrences = 1) intercept {
   anotherSystem.actorOf(Props(classOf[Supervisor], new ConfigurationFromStatic(configsAnother), metrics), "AnotherSupervisor")
}

And that waits until timeouts (I even see the log message), but I guess that EventFilter is reading only from the "main" actor system created by TestKit.

Any idea or suggestion on how to deal with this scenario?

1
I went with an empty while until the actorSelection.resolveOne() gets one, but seems like an awful way to do it.Fede E.

1 Answers

2
votes

A more reliable and consistent way is to let known actors introduce you to more actors: in this case the supervisor is the entry point through which communication should start. You can either forward all messages through this actor or you add a lookup protocol for the child actors where others can ask the supervisor for their ActorRefs.

ActorSelection is intended only for the initial communication between remote nodes to obtain the first ActorRef. From there on it is much better to just use messages as described above.