Akka:如何确保消息已被接收



我有一个演员分配器。它的作用就是它

  1. 根据要求分配一些物品
  2. 倾听新来的人

代码如下

class Dispenser extends Actor {
    override def receive: Receive = {
        case Get =>
            context.sender ! getObj()
        case x: SomeType =>
            addObj(x)
    }
}

在实际处理中,从发送新对象到分配器开始分配它之前,是否经过 1 毫秒甚至几秒钟并不重要,因此没有代码跟踪它。

但是现在我正在为分配器编写测试,我想确保首先它接收新对象,然后才收到 Get 请求。

这是我想出的测试代码:

val dispenser = system.actorOf(Props.create(classOf[Dispenser]))
dispenser ! obj
Thread.sleep(100)
val task = dispenser ? Get()
val result = Await.result(task, timeout)
check(result)

它满足一个重要的要求 - 它不会更改原始代码。但它是

  1. 即使在非常高性能的盒子上也至少慢 100 毫秒
  2. 不稳定,有时会失败,因为 100 毫秒或任何其他常量不提供任何保证。

问题是如何进行满足要求并且没有上述缺点(也没有任何其他明显缺点)的测试

你可以拿出Thread.sleep(..),你的测试会很好。 Akka保证您需要的订单。

使用代码

dispenser ! obj
val task = dispenser ? Get()

dispenser将在确定性Get之前处理obj,因为

  1. 同一线程将obj然后Get放入演员的邮箱中,因此它们在演员邮箱中的顺序正确
  2. 执行组件按顺序处理邮件,
  3. 一次处理一封邮件,因此执行组件将接收这两封邮件,并按照它们在邮箱中排队的顺序进行处理。

(..如果没有其他事情没有发生在您的示例代码中 - 路由器、getObj 或 addObj 中的异步处理、存储......

Akka FSM 模块对于测试参与者的底层状态和行为非常方便,并且不需要专门为测试更改其实现。通过使用TestFSMRef,可以通过以下方式获取参与者的当前状态和数据:

val testActor = TestFSMRef(<actors constructor or Props>)
testActor.stateName shouldBe <state name>
testActor.stateData shouldBe <state data>

http://doc.akka.io/docs/akka/2.4.1/scala/fsm.html

最新更新