We have an actor that we are writing unit tests for, and as part of the tests we want to assert that certain messages are sent to another actor in a certain order. In our unit tests, the actor receiving the messages is represented by an Akka TestProbe
, which gets injected into the actor under test when it is created.
It is no problem to assert that the messages were sent to the test probe, however we have been struggling to work out a way to assert they are sent in the correct order (we could not find any suitable methods for doing this in the documentation). Any ideas how we achieve this?
Below is a minimal implementation that highlights the problem.
Implementation
case class Message(message: String)
case class ForwardedMessage(message: String)
class ForwardingActor(forwardTo: ActorRef) extends Actor {
def receive = {
case Message(message) =>
forwardTo ! ForwardedMessage(message)
}
}
Unit Test
class ForwardMessagesInOrderTest extends TestKit(ActorSystem("testSystem"))
with WordSpecLike
with MustMatchers {
"A forwarding actor" must {
val forwardingReceiver = TestProbe()
val forwardingActor = system.actorOf(Props(new ForwardingActor(forwardingReceiver.ref)))
"forward messages in the order they are received" in {
forwardingActor ! Message("First message")
forwardingActor ! Message("Second message")
// This is the closest way we have found of achieving what we are looking for, it asserts
// that both messages were received, but doesn't assert correct order. The test will pass
// regardless which way round we put the messages below.
forwardingReceiver.expectMsgAllOf(
ForwardedMessage("Second message"),
ForwardedMessage("First message"))
}
}
}
I'm going to suggest two changes to your test spec. First, when creating the actor under test, use a TestActorRef
like so:
val forwardingActor = TestActorRef(new ForwardingActor(forwardingReceiver.ref))
Using a TestActorRef
will assure that the CallingThreadDispatcher
is used, removing any complications from testing async code (which an actor is). Once you do that, you can change your assertions to:
forwardingReceiver.expectMsg(ForwardedMessage("First message"))
forwardingReceiver.expectMsg(ForwardedMessage("Second message"))
These assertions are inherently In-Order, so if things came in out of this order, they will fail. This should fix your issues.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With