在下面的代码中:
TestKit probe = new TestKit(system); // line 1
ActorRef deviceActor = system.actorOf(Device.props("group", "device")); // line 2
deviceActor.tell(new DeviceManager.RequestTrackDevice("group", "device"), probe.getRef()); // line 3
probe.expectMsgClass(DeviceManager.DeviceRegistered.class); // line 4
assertEquals(deviceActor, probe.getLastSender()); // line 5
如果我注释掉第4行,则测试失败。第3行足以将消息发送给演员。那么4号线到底在做什么呢?
要了解发生了什么,让我们检查一下源代码。
以下是getLastSender()
的定义,其中p
是TestProbe
:
public ActorRef getLastSender() {
return p.lastMessage().sender();
}
lastMessage
在TestKit.scala
中声明如下:
private[akka] var lastMessage: Message = NullMessage
lastMessage
变量以两种方法之一receiveWhile
和receiveOne
进行突变。 expectMsgClass
方法称后者:
def expectMsgClass[C](max: FiniteDuration, c: Class[C]): C = expectMsgClass_internal(max.dilated, c)
private def expectMsgClass_internal[C](max: FiniteDuration, c: Class[C]): C = {
val o = receiveOne(max)
// ...
}
基本上,如果你没有在测试中调用其中一个TestKit
的内置断言(例如,expectMsg*
方法之一),那么lastMessage
将保持不变为NullMessage
。如果lastMessage
是NullMessage
,那么调用lastMessage.sender
将导致异常,并且测试中的assertEquals(deviceActor, probe.getLastSender());
将失败。
另一方面,如果你确实调用了内置的断言,例如expectMsgClass
,那么lastMessage
将被正确设置,lastMessage
的发送者将正确解析。
简而言之,调用getLastSender()
假定使用TestKit
断言。这是在documentation(强调我的)中暗示的:
探针存储最后出列的消息的发送者(即在其接收
expectMsg*
之后),其可以使用getLastSender()
方法检索。