I have an actor Dispenser. What it does is it
- dispenses some objects by request
- listens to arriving new ones
Code follows
class Dispenser extends Actor {
override def receive: Receive = {
case Get =>
context.sender ! getObj()
case x: SomeType =>
addObj(x)
}
}
In real processing it doesn't matter whether 1 ms or even few seconds passed since new object was sent until the dispenser starts to dispense it, so there's no code tracking it.
But now I'm writing test for the dispenser and I want to be sure that firstly it receives new object and only then it receives a Get request.
Here's the test code I came up with:
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)
It satisfies one important requirement - it doesn't change original code. But it is
- At least 100ms seconds slow even on very high performance boxes
- Unstable and fails sometimes because 100 ms or any other constant doesn't provide any guaranties.
And the question is how to make a test that satisfies requirement and doesn't have cons above (neither any other obvious cons)
You can take out the
Thread.sleep(..)
and your test will be fine. Akka guarantees the ordering you need.With the code
dispenser
will processobj
beforeGet
deterministically becauseobj
thenGet
in the actor's mailbox, so they're in the correct order in the actor's mailbox(..if there's nothing else going on that's not in your sample code - routers, async processing in getObj or addObj, stashing, ..)