Here is an example of a bullying planner, as described in @lmm. In this example, we really test the complete planning and processing of the action as two separate scenarios. The first testing, which gave some condition (a message of a certain type, which was received in my example), we plan a callback, and the second - processing a message that returns to itself when this timer is turned off. The code is as follows:
object TimerExampleActor{ case object ClearState case class ScheduleStateClearing(duration:FiniteDuration) } class TimerExampleActor extends Actor{ import TimerExampleActor._ var state:List[Int] = Nil def receive = { case ScheduleStateClearing(d) => scheduler.scheduleOnce(d, self, ClearState)(context.dispatcher) case ClearState => state = Nil } def scheduler = context.system.scheduler }
Then, using specs2 and mockito, my test case looks like this:
class TimerExampleActorTest extends Specification with Mockito with NoTimeConversions{ import TimerExampleActor._ implicit val system = ActorSystem("test") trait testscope extends Scope{ val mockScheduler = mock[Scheduler] val actor = TestActorRef(new TimerExampleActor{ override def scheduler = mockScheduler }) } "A request to schedule state clearing" should{ "schedule a callback for the message ClearState to self with the supplied duration" in new testscope{ val dur = 1.minute actor ! ScheduleStateClearing(dur) there was one(mockScheduler).scheduleOnce(dur, actor, ClearState)(actor.underlyingActor.context.dispatcher) } } "A ClearState message received by the actor" should{ "clear the interval 'state' List" in new testscope{ actor.underlyingActor.state = List(1,2,3) actor ! ClearState actor.underlyingActor.state mustEqual Nil } } }
You can see that when I create an actor instance under testing, I override the method I created to get the scheduler instance, allowing me to return the layout. This is not the only way to test for something like this, but it can certainly be one option for you.
source share