我正在写一个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
实例化为目标,但结果是相同的。任何线索?
答案 0 :(得分:0)
事实证明答案实际上非常简单:测试运行得如此之快以至于MyActor
将Identify
消息发送到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所述。