1

In the code below:

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

If I comment out line 4, the test fails. Line 3 is enough to send the message to the actor. So what exactly line 4 is doing?

4

1 回答 1

1

要了解发生了什么,让我们检查源代码。

这是 的定义getLastSender(),其中p是 a 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's 的内置断言之一(例如,其中一种expectMsg*方法),那么lastMessage将保持不变为NullMessage. 如果lastMessage是 a NullMessage,那么调用lastMessage.sender将导致异常,并且assertEquals(deviceActor, probe.getLastSender());在您的测试中将失败。

另一方面,如果您确实调用了内置断言,例如expectMsgClass, thenlastMessage将被适当地设置,并且发送者lastMessage将正确解析。

简而言之,调用getLastSender()假定使用TestKit断言。这在文档中有所暗示(强调我的):

探测器存储最后一个出队消息的发送者(即在其expectMsg*接收之后),可以使用该getLastSender()方法检索该消息。

于 2018-03-02T14:27:26.827 回答