我有一个演员分配器。它的作用就是它
- 根据要求分配一些物品
- 倾听新来的人
代码如下
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)
它满足一个重要的要求 - 它不会更改原始代码。但它是
- 即使在非常高性能的盒子上也至少慢 100 毫秒
- 不稳定,有时会失败,因为 100 毫秒或任何其他常量不提供任何保证。
问题是如何进行满足要求并且没有上述缺点(也没有任何其他明显缺点)的测试
你可以拿出Thread.sleep(..)
,你的测试会很好。 Akka保证您需要的订单。
使用代码
dispenser ! obj
val task = dispenser ? Get()
dispenser
将在确定性Get
之前处理obj
,因为
- 同一线程将
obj
然后Get
放入演员的邮箱中,因此它们在演员邮箱中的顺序正确
执行组件按顺序处理邮件, - 一次处理一封邮件,因此执行组件将接收这两封邮件,并按照它们在邮箱中排队的顺序进行处理。
(..如果没有其他事情没有发生在您的示例代码中 - 路由器、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