Testing timer events in acc

I have a function that uses scheduleOnce to schedule an event that will happen some time in the future, and I want to write a test that checks that:

  • event really planned
  • it was planned at the right time
  • the system behaves as expected when this event ultimately triggers

but I don’t want the test to actually wait a few minutes without doing anything.

What is the best way to check the code that uses akka Scheduler?

+6
source share
2 answers

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.

+4
source

Make the scheduler a time parameter. Use a shorter time in your test than in your regular code.

Or ... when testing, you can mix in a special attribute that modifies your class as needed (reduces waiting time.)

0
source

Source: https://habr.com/ru/post/978164/


All Articles