使用ActorSelection识别Actor

时间:2016-03-05 18:44:26

标签: scala akka akka-testkit

我正在写一个Actor,应该看另一个Actor;我们将后者称为目标。一旦目标停止,我的Actor就应该停止。对于这个目标,我只有一个ActorSelection。要观看它,我显然需要ActorRef,所以我想我应该发送ActorSelection Identify消息;当它回复ActorIdentity时,我会得到ActorRef。到目前为止一切都那么好,但我无法让它发挥作用。

这是规范:

// Arrange
val probe = TestProbe()
val target = TestProbe().ref
val sut = system.actorOf(MyActor.props(system.actorSelection(target.path)), "watch-target")
probe watch sut

// Act
target ! PoisonPill

// Assert
probe.expectTerminated(sut)

实施(FSM,跳过详细信息):

log.debug("Asking target selection {} to identify itself; messageId={}", selection.toString(), messageId)
selection ! Identify(messageId)

when(Waiting) {
  case Event(ActorIdentity(`messageId`, Some(ref)), Queue(q)) =>
    log.info("Received identity for remote target: {}", ref)
    context.watch(ref)
    goto(NextState) using TargetFound(ref)
  case Event(ActorIdentity(`messageId`, None), Queue(q)) =>
    log.error("Could not find requested target {}", selection.toString())
    stop()
}

initialize()

现在,当我运行我的测试时,它是绿色的,因为被测系统确实停止了。但问题是它停止了,因为它无法使用上述步骤找到目标。日志文件说:

  

要求目标选择ActorSelection [Anchor(akka:// default /),Path(/ system / testProbe-3)]来标识自己; MESSAGEID = 871823258

     

找不到请求的目标ActorSelection [Anchor(akka:// default /),Path(/ system / testProbe-3)]

我错过了一些明显的东西吗?也许TestProbe不应该透露它的真实身份?我甚至尝试将虚拟Actor实例化为目标,但结果是相同的。任何线索?

2 个答案:

答案 0 :(得分:0)

事实证明答案实际上非常简单:测试运行得如此之快以至于MyActorIdentify消息发送到selection之前,选择背后的Actor已收到PoisonPill因此被杀死。

在发送Thread.sleep()之前添加一点PoisonPill来解决问题。

答案 1 :(得分:0)

目标参与者在发出识别请求之前被终止。这是因为Akka only guarantees order when sending messages between a given pair of actors

如果您在以下行上方添加thread.sleep,则识别请求应该会成功。

Thread.sleep(100)
// Act
target ! PoisonPill

请注意,可能有更好的方法来编写测试代码 - 睡眠线程并不理想。

您的观看演员还应处理目标演员的Terminated消息,如here所述。