0

我正在写一个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)]

我在这里遗漏了一些明显的东西吗?也许aTestProbe不应该透露其真实身份?我什至尝试将虚拟对象实例Actor化为目标,但结果是相同的。有什么线索吗?

4

2 回答 2

0

在发出识别请求之前,目标参与者将被终止。这是因为Akka 仅在给定的 Actor 对之间发送消息时保证顺序

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

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

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

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

于 2016-03-05T19:15:39.997 回答
0

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

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

于 2016-03-05T19:12:17.057 回答