0
case class FeatureFilter(s3Client: AmazonS3) extends Actor with ActorLogging {

  override def preStart(): Unit = {
    self ! Initialize
  }

  override def receive: Receive = {
    case Initialize =>
        // long running operaton
        val tryfile = S3Connection(s3Client).downloadObject(...)

          tryfile match {
            case Success(file) =>
                  context.become(active(file))

            case Failure(exception) =>
              self ! PoisonPill
          }
  }
  def active(file: File): Receive = {
    case Query(key) =>
        // do some processing and reply to sender

  }
}

I am using below test for above actor:

"an actor" should {
    // mocked S3 client
    val client = ...

    "test for presence of keys" in {

      val actor = system.actorOf(Props(FeatureFilter(client)))

      for (i <- 1 to 100) {
        actor ! Query("test_string")
        expectMsg(SomeMessage)
      }
    }
}

The above test fails with

java.lang.AssertionError: assertion failed: timeout (3 seconds) during expectMsg while waiting ...

I think this is because when the message actor ! Query("test_string") is sent to actor, it's handler is still receive, and so it doesn't respond, and hence the timeout.

But I even tried adding the handler for Query(key) in the receive method (just like in active method). Still I am getting the same error.

  1. Could someone please point what is the issue here ?

  2. Also when I move the S3 download task to preStart(), still the issue remains same. Isn't preStart() a blocking call ? How would the code in the test proceed until the preStart() is completed ?

Sumit Jha
  • 2,095
  • 2
  • 21
  • 36

1 Answers1

0

akka stash sounds like the way you looking for. In case of any message that the actor support but is unhandled add on stash and unapply all if active is reached. look at actor stash for documentation and example usage

may your code would look like

case msg => stash()

...
unstashAll()
context.become(active(file))