Akka Typed - 如何将终止消息发送到 BehaviorTestKit

Akka Typed - How to sent Terminated message to BehaviorTestKit

我正在尝试对我的演员对儿童演员的“已终止”消息的处理进行单元测试。被测代码是这样的:

    case Terminated(terminatedActor) =>
      val actorName = terminatedActor.path.name
      if (actorName.startsWith("ChildActor")) {
        doSomething()
      }
      Behaviors.same

在我的单元测试中,我试图做这样的事情:

    val testInbox = TestInbox[ParentActor.Request](name = "ChildActor1")
    val testKit = BehaviorTestKit(ParentActor())
    testKit.run(Terminated(testInbox.ref))
    assert( *** that doSomething() happened *** )

单元测试代码无法编译。我在调用 testKit.run():

时收到此错误

类型不匹配; 发现:akka.actor.typed.Terminated 要求:ParentActor.Request

我假设这是因为 Terminated 消息没有继承我的 ParentActor.Request 特征。

根据以下评论,我将单元测试更改为:

    val testInbox = TestInbox[ParentActor.Request](name = "ChildActor1")
    val testKit = BehaviorTestKit(ParentActor())
    testKit.signal(Terminated(testInbox.ref))
    assert( *** that doSomething() happened *** )

这现在可以编译,但是对 testKit.signal() 的调用现在会抛出 DeathPactException,文档说这意味着 actor 没有处理 Terminated 消息,即使我的生产代码肯定会处理它。

知道哪里出了问题吗?

您确定您的生产代码确实可以处理 Terminated 信号吗?

从类型 Behavior 的角度来看,信号不是消息。它们由 receiveSignal 安装的信号处理程序处理。该信号处理程序不仅接收信号,还接收 ActorContext,并封装在一个元组中。如果对 Terminated 信号的响应不需要上下文,您仍然需要匹配它:

// inside a .receiveSignal...
case (_, Terminated(terminatedActor)) =>
  val actorName = terminatedActor.path.name
  if (actorName.startsWith("ChildActor")) {
    doSomething()
  }
  Behaviors.same

请注意,当通过 testKit.signal:

发送时,Akka 的测试套件包括 this test which exercises handling the Terminated signal
      val other = TestInbox[String]()
      val testkit = BehaviorTestKit[Parent.Command](Parent.init)
      noException should be thrownBy {
        testkit.signal(Terminated(other.ref))
      }