如何基于ActorSelection模拟一个actor?(涉及IT技术)

4

我已经搜索了很多关于这个问题的资料,但是还没有找到答案。

我有一个演员"A" (用户/A),当接收到消息"M"时,会向另一个演员"B" (用户/B) 发送消息"X"。为了实现这一点,演员A使用了ActorSelection。 我需要测试一下,当我发送MA时,B是否会收到"X"。

我尝试使用TestProbe在"用户/B"上进行测试,但并没有成功。

我也看到一些类似的问题,但每个答案都说要使用ActorRef而不是ActorSelection。这对我来说不是一个选择,我真的需要使用ActorSelection。

有人有什么想法吗?


为什么需要使用ActorSelection - Ryan
1
在我的情况下,我有很多位于路径“/user/agents/*”上的演员,但这些演员是易变的,并且我没有所有演员的“ActorRef”。另一方面,我有一个演员“/user/xpto”,它向“/user/agents/*”发送消息“X”,总是接收到消息“M”。我不明白为什么在Akka系统中模拟某些演员如此复杂。 - Rafael Pacheco
2个回答

6
简单回答:不要在A中硬编码选择路径,而是使其可配置。在测试中,您可以将其指向TestProbe的路径。

值得注意的是,在当前版本的Akka中,由于无法控制TestProbe名称(http://doc.akka.io/api/akka/2.3.14/index.html#akka.testkit.TestProbe$),因此这可能更难实现。但在最新的Release candidate中,有一个新的“apply”方法可以设置名称:http://doc.akka.io/api/akka/2.4.0-RC2/index.html#akka.testkit.TestProbe$。 - mattinbits
2
你不需要控制名称,因为你可以从 probe.ref.path 中获取它。 - Roland Kuhn

5
你可以编写简单的测试辅助函数,它们的名称与你的参与者相同,但会将消息转发给你的探针。
假设这是你的设置(简化版):
case object M
case object X
class A extends Actor {
  def receive = {
    case M => context.system.actorSelection("/user/B") ! X
  }
}

你想测试演员A

你可以为你的应用编写这种“测试框架”:

object ForwardActor {
  def props(to: ActorRef) = Props(new ForwardActor(to))
}

class ForwardActor(to: ActorRef) extends Actor {
  override def receive = {
    case x => to forward x
  }
}

def mock(name: String, probe: TestProbe)(implicit system: ActorSystem): Unit = 
  system.actorOf(ForwardActor.props(probe.ref), name)

然后,您可以通过简单进行以下类型的测试来测试演员 A

"A sends X to B after receiving M" in {
  val probeB = TestProbe()
  mock("B", probeB)
  system.actorOf(Props(new A)) ! M
  probeB expectMsg X
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接