I'm trying to unit test my actor's handling of a "Terminated" message for a child actor. The code under test is something like this:
case Terminated(terminatedActor) =>
val actorName = terminatedActor.path.name
if (actorName.startsWith("ChildActor")) {
doSomething()
}
Behaviors.same
In my unit test, I'm trying to do something like this:
val testInbox = TestInbox[ParentActor.Request](name = "ChildActor1")
val testKit = BehaviorTestKit(ParentActor())
testKit.run(Terminated(testInbox.ref))
assert( *** that doSomething() happened *** )
The unit test code doesn't compile. I get this error in the call to testKit.run():
type mismatch; found : akka.actor.typed.Terminated required: ParentActor.Request
I assume that this is because the Terminated message does not inherit from my ParentActor.Request trait.
Based on a below comment, I changed the unit test to:
val testInbox = TestInbox[ParentActor.Request](name = "ChildActor1")
val testKit = BehaviorTestKit(ParentActor())
testKit.signal(Terminated(testInbox.ref))
assert( *** that doSomething() happened *** )
This now compiles, but the call to testKit.signal() now throws a DeathPactException, which the docs say means that the actor is not handling the Terminated message, even though my production code definitely does handle it.
Any idea what is wrong?
Are you sure that your production code definitely handles the Terminated
signal?
Signals are not, from the perspective of a typed Behavior
, messages. They are processed by the signal handler installed by receiveSignal
. That signal handler takes not just the signal but the ActorContext
as well, wrapped up in a tuple. If the response to a Terminated
signal doesn't require the context, you still have to match against it:
// inside a .receiveSignal...
case (_, Terminated(terminatedActor)) =>
val actorName = terminatedActor.path.name
if (actorName.startsWith("ChildActor")) {
doSomething()
}
Behaviors.same
Note that Akka's test suite includes this test which exercises handling the Terminated
signal when sent via testKit.signal
:
val other = TestInbox[String]()
val testkit = BehaviorTestKit[Parent.Command](Parent.init)
noException should be thrownBy {
testkit.signal(Terminated(other.ref))
}