I have an actor that uses become to change from an inactive to active state, and handles messages differently based on such state changes. I want to be able to test that the actor behaves correctly in each state by ignoring messages that are invalid for a given state. Initially I incorrectly believed that UnhandledMessage was some sort of exception that would be raised and I'd intercept it that way. (Though I was skeptical since it isn't UnhandledMessageException.)

Here's a contrived example that represents an actor changing behavior from active to inactive:

/* src/main/com/deploymentzone/UnexpectedMessages.scala */  
⋮
case object On  
case object Off  
case class TransmitData(data : Any)  
case object Transmitted

class Throttler extends Actor with ActorLogging {

  def inactive : Receive = {
    case On => context.become(active)
  }

  def active : Receive = {
    case Off => context.become(inactive)
    case TransmitData(data) =>
      log.info(s"transmitting $data")
      sender ! Transmitted
  }

  def receive = inactive
}

The above example is pretty straightforward: when Off (the initial, inactive state) other messages the actor receives are ignored - they will result in UnhandledMessage being sent back to the sender. When the Throttler instance receives the On message it swaps its behavior for the active state which can handle the arbitrary TransmitData message.

Here's how to verify the behavior acts as expected:

 /* src/test/com/deploymentzone/UnexpectedMessagesSpec.scala */  
⋮
class UnexpectedMessagesSpec  
  extends TestKit(ActorSystem("UnexpectedMessagesSpec"))
  with ImplicitSender
  with WordSpecLike
  with Matchers
  with BeforeAndAfterAll {

  override def afterAll() {
    system.shutdown()
  }

  "Throttler" should {
    "not respond to TransmitData when inactive" in {
      val subject = TestActorRef(Props(new Throttler))

      system.eventStream.subscribe(testActor, classOf[UnhandledMessage])
      subject ! TransmitData("data")

      expectMsg(UnhandledMessage(TransmitData("data"), testActor, subject))
    }
    ⋮
  }
}

The spec above subscribes the implicitly provided testActor to the event stream listening for UnhandledMessage instances. Since the spec also includes the ImplicitSender trait the same testActor is also considered the sender for any messages which allows a verification of the expected behavior through expectMsg.

For completion's sake here's another test checking the On behavior:

  
   ⋮
   "respond to TransmitData when active" in {
      val subject = TestActorRef(Props(new Throttler))

      subject ! On
      subject ! TransmitData("all systems go")

      expectMsg(Transmitted)
    }

I've published the complete example to Github.