There are two actors - ProducerActor
and ConsumerActor
. Producer has a scheduler which sends "Tick"
message to itself each 2000 ms
. After that the producer sends "Hello"
message to consumer:
class ProducerActor(consumer: ActorRef) extends Actor {
override def receive: Receive = {
case "Tick" =>
...
// some code which takes < 1 ms
...
consumer ! "Hello"
}
override def preStart: Unit =
context.system
.scheduler
.schedule(2000 milliseconds, 2000 milliseconds, self, "Tick")
}
Is it possible to test the case when the consumer actor receives a "Hello" message each 2000 ms
? So, if message is received in period < 2000 ms
or > 2000 ms
then test will assert error.
For example:
"Consumer test" should {
"receive message each 2000 ms" in {
...
val consumer = TestProbe()
val producer = system.actorOf(Props(new ProducerActor(consumer.ref))
...
consumer.howToExpectDelayedMessage(minDelay = 2000 millis, "Hello")
}
}
--- UPD ---
I have figured out the following solution which works fine for me:
"Consumer test" should {
"receive message each 2000 ms" in {
val consumer = TestProbe()
val producer = system.actorOf(Props(new ProducerActor(consumer.ref))
// check the first ten periods
(0 to 10) foreach { _ =>
consumer.expectNoMsg(2000 millis)
consumer.expectMsg("Hello")
}
}
}
But if there is a better solution for this task it would be great if you could share.
You can use Timing Assessions to do that.
certain events must not happen immediately (like a timer), others need to happen before a deadline. Therefore, all examination methods accept an upper time limit within the positive or negative result must be obtained.
import akka.actor.Props
import scala.concurrent.duration._
val worker = system.actorOf(Props[Worker]())
within(200 millis) {
worker ! "some work"
expectMsg("some result")
expectNoMessage() // will block for the rest of the 200ms
Thread.sleep(300) // will NOT make this block fail
}
The block given to within must complete after a duration which is between min and max, where the former defaults to zero.