I've blogged previously about testing messages sent back to the sender and to a child actor. The final common scenario I come across is testing actors that send a messages back to its supervisor/parent. If it is in response to a message from the parent you can use the same technique as described in testing messages sent back to the sender.
However, if that is not the case then TestKit has a very simple way you can do it with the TestActorRef and a TestProbe. Any where you have a piece of code that looks like this:
context.parent ! "Any message"
For example:
Then you can test it by passing a TestProbe to your TestActorRef and using the expect* functions on the TestProbe. So to test the actor above your test will look something like this:
As you can see the TestActorRef can take an ActorRef to use as a parent when you use the apply method that takes in a Props.
Full code here. Happy testing.
Showing posts with label akka. Show all posts
Showing posts with label akka. Show all posts
Monday, February 10, 2014
Wednesday, February 5, 2014
Akka: Testing messages sent to child actors
I previously blogged about testing messages sent back to the sender. Another common scenario is testing that an actor sends the correct message to a child. A piece of code that does this might look like:
But how do you test drive this kind of code?
I've adopted the approach of removing the responsibility of creating the child from the ParentActor. To do this you can pass in a factory to the ParentActor's constructor that can be replaced for testing. To do this the ParentActor is changed to look like this:
The ParentActor now takes in a factory function which takes in an ActorFactoryRef and returns a ActorRef. This function is responsible for creating the ChildActor.
childFactory: (ActorRefFactory) => ActorRef
This is then used by the ParentActor as follows:
val childActor = childFactory(context)
You can now inject a TestProbe for testing rather than using a real ActorFactorRef. For example:
And for the real code you can pass in an anonymous function that uses the ActorRefFactory to actually create a real ChildActor:
Here you can see the ActorFactoryRef (context in Actors implement this interface) is used to create an Actor the same way as the original ParentActor did.
Full source code here.
But how do you test drive this kind of code?
I've adopted the approach of removing the responsibility of creating the child from the ParentActor. To do this you can pass in a factory to the ParentActor's constructor that can be replaced for testing. To do this the ParentActor is changed to look like this:
The ParentActor now takes in a factory function which takes in an ActorFactoryRef and returns a ActorRef. This function is responsible for creating the ChildActor.
childFactory: (ActorRefFactory) => ActorRef
This is then used by the ParentActor as follows:
val childActor = childFactory(context)
You can now inject a TestProbe for testing rather than using a real ActorFactorRef. For example:
And for the real code you can pass in an anonymous function that uses the ActorRefFactory to actually create a real ChildActor:
Here you can see the ActorFactoryRef (context in Actors implement this interface) is used to create an Actor the same way as the original ParentActor did.
Full source code here.
Tuesday, January 14, 2014
Akka: Testing that an actor sends a message back to the sender
A common pattern when using actors is for actor A to send a message to Actor B and then for Actor B to send a message back.
This can be tested using the Akka testkit along with Scala Test.
Take the following very simple example. We have an Actor called Server which should accept Startup messages and respond with a Ready message when it is ready for clients to send additional messages.
We can start with a noddy implementation that does nothing:
Then write a test to specify the behaviour. Here I've used TestKit along with Scala Test FunSuite.
This test will fail with the following error message:
assertion failed: timeout (3 seconds) during expectMsg while waiting for Ready
As you can probably guess TestKit waited for 3 seconds for a Ready message to be sent back.
To fix the test we add the the following to the Server Actor implementation:
And now the test will pass! The two important things to take note of are that our test case extended from TestKit, this gives you an ActorSystem. And that the test case mixed in the ImplicitSender trait, this allows us to receive messages use the methods like "expectMsg" to assert that the correct message has been received.
This can be tested using the Akka testkit along with Scala Test.
Take the following very simple example. We have an Actor called Server which should accept Startup messages and respond with a Ready message when it is ready for clients to send additional messages.
We can start with a noddy implementation that does nothing:
Then write a test to specify the behaviour. Here I've used TestKit along with Scala Test FunSuite.
This test will fail with the following error message:
assertion failed: timeout (3 seconds) during expectMsg while waiting for Ready
As you can probably guess TestKit waited for 3 seconds for a Ready message to be sent back.
To fix the test we add the the following to the Server Actor implementation:
And now the test will pass! The two important things to take note of are that our test case extended from TestKit, this gives you an ActorSystem. And that the test case mixed in the ImplicitSender trait, this allows us to receive messages use the methods like "expectMsg" to assert that the correct message has been received.
Subscribe to:
Posts (Atom)