score:15

Accepted answer

An actor sending to itself is very much an intimiate detail of how that actor performs a certain function, hence I would rather test the effect of that message than whether or not that message has been delivered. I’d argue that sending to self is the same as having a private helper method on an object in classical OOP: you also do not test whether that one is invoked, you test whether the right thing happened in the end.

As a side note: you could implement your own message queue type (see https://doc.akka.io/docs/akka/snapshot/mailboxes.html#creating-your-own-mailbox-type) and have that allow the inspection or tracing of message sends. The beauty of this approach is that it can be inserted purely by configuration into the actor under test.

score:0

In the past, I have overridden the implementation for ! so that I could add debug/logging. Just call super.! when you're done, and be extra careful not to do anything that would throw an exception.

score:0

I had the same issue with an FSM actor. I tried setting up a custom mailbox as per the accepted answer but a few minutes didn't get it working. I also attempted to override the tell operator as per another answer but that was not possible as self is a final val. Eventually I just replaced:

 self ! whatever

with:

 sendToSelf(whatever)

and added that method into the actor as:

// test can override this
protected def sendToSelf(msg: Any) {
  self ! msg
}

then in the test overrode the method to capture the self sent message and sent it back into the fsm to complete the work:

  @transient var sent: Seq[Any] = Seq.empty

  val fsm = TestFSMRef(new MyActor(x,yz) {
    override def sendToSelf(msg: Any) {
      sent = sent :+ msg
    }
  })

  // yes this is clunky but it works
  var wait = 100
  while( sent.isEmpty && wait > 0 ){
    Thread.sleep(10)
    wait = wait - 10
  }

  fsm ! sent.head

Related Query