Testing Akka: actors, dependency injection and mocks

I’ve been digging into what the expected way is to test my small Akka system, as described in my previous post on the subject. I think my problem partially arises from being unclear as to the proper mode of dependency injection in Akka. In other words, I don’t know what the proper way is for my Root actor to obtain a reference to its Database and HTTP sub-actors. Does it create them itself? Look them up from a service locator? And what if I need to inject mock actors into the system in some parts in order to test it?

Various bits of Akka documentation suggest different approaches to wiring actors together; for instance, this page in the official docs suggests either passing dependent actors as constructor arguments, creating them in a preStart() method, or passing them to their referring actors in a message and using become() to switch between initialization states. This example from the testkit docs takes the latter approach, but I can’t say I like the result:

class MyDoubleEcho extends Actor {
  var dest1: ActorRef = _
  var dest2: ActorRef = _
  def receive = {
    case (d1: ActorRef, d2: ActorRef) =>
      dest1 = d1
      dest2 = d2
    case x =>
      dest1 ! x
      dest2 ! x
  }
}
/* ... */

val probe1 = TestProbe()
val probe2 = TestProbe()
val actor = system.actorOf(Props[MyDoubleEcho])
actor ! (probe1.ref, probe2.ref)
actor ! "hello"
probe1.expectMsg(500 millis, "hello")
probe2.expectMsg(500 millis, "hello")

This does seem to work, but it seems to me that it pollutes the actor with a bunch of test-related code that probably doesn’t belong in production (by which I mean the receive pattern which takes the two dest parameters).

I have found an interesting take on this question in this presentation by Roland Kuhn, introducing akka-testkit from Scala Days 2012—the entire presentation is worth watching, but the part I’m interested in starts at around 22:05 or so.  After a not terribly helpful note about how if you have difficulty injecting mocks into your code, then there is probably something wrong with your design (there may be something to that, but it’s not all that helpful to hear when you’re looking for a solution for injection), Mr. Kuhn mentions a third option for users of the (then-new) Akka 2.0: actors can use actor path naming to look up their dependent actors; the test ActorSystem can then supplant the real implementations with mocks at the same locations.

Of course, all of this sort of assumes that you have a way of separating out actor creation and lifecycle control from dependency injection itself. A lot of the other Akka literature I’ve read seems to posit the integrated lifecycle management bits of Akka as a feature, right down to the “Let It Crash” maxim on the public Akka blog, and all of these features seem to be in direct opposition to the inversion of control notions that most dependency injection systems are founded on. In the last part of Mr. Kuhn’s talk above, he suggests breaking up actor models into somewhat discrete trees, which then use service locators or similar things to find one another; this might be something I can look into.

There was also a talk at this year’s Scala Days about integrating Spring and Akka, which might have some merit for this purpose, and I recently ran across this promising post which describes an approach to autowiring actors with Spring and Akka 2.2 (in Java). Overall, though, this doesn’t seem to be a problem with a clear solution.

Adventures in Akka

My current technical interest, mercurial as ever, is in Akka. My present employer is mostly a java shop, but they are open-minded and I have a notion to prototype out a rewrite of a simple system there into Akka and Scala.  The system is probably one of the simpler ones we have, known as the “notification service.” It periodically checks for new rows in a particular database table.  If it finds any, it fires off a JSON-formatted request to a REST web service, the “delivery service”; if it gets a successful response from this service it will mark the message as delivered in the database. There are a few wrinkles related to locking, and there are actually a few different web services involved, but that’s pretty much the basics. Something possessed me to make a diagram of the existing flow: 

Image

 

The purpose of this system is to deliver notifications to particular users, with the idea being that any subsystem which needs to send a notification to someone can put the right data in the database, where this system will pick up up and hand it off to an existing REST service which winds up doing most of the heavy lifting.  The existing service is implemented in Java and Spring, using Quartz as a cron job to kick off a polling method once every 30 minutes or so (we don’t need this service to run particularly swiftly).

It’s not really hard to see how this would translate into a message-based actor model in Scala.  You’d probably have one root actor coordinating things.  You’d have an actor talking to the database, maybe with a supervisor to restart it as needed, and you’d have another actor to handle the HTTP client calls.  Most likely the client actor would spawn off a new actor per individual row of data, and have each of these worker actors make a single HTTP request. On a success, the worker would send a message back to the database actor to update the database row as “completed”; on a failure the worker might just log an error and die.

A rough sketch of that might look like this (pardon my sub-par OmniGraffle skills):

Image

Note that the single-line arrows here represent the actor supervision hierarchy, not message-passing.  I’m also not positive that the “DB Worker” actor needs to exist, versus just having the “Database” actor do the work, but it simplifies things to do it this way and I suppose there might be more than one of those (more on this later).

I’m been struggling a bit to come up with a good way to represent message passing in a diagram, but I think I’ve got the gist of the design in this one:

Image

Everything is started by Tick messages which are sent to the root object every 5 seconds via Akka’s scheduler interface (this would be more like 15-30 minutes in production).  This causes the root actor to pass a PollDatabase message to the Database actor; the message includes a reference to the HTTP Client actor.  For each notification row the Database actor finds in the database, it sends a Notify message to the HttpClient actor.  This actor composes a MakeRequest message to one of a pool of Worker actors, including the data from the database and a reference to the Database actor.  The Worker performs the HTTP request; if it is successful it sends a RequestSucceeded message to the Database actor, which will ask a DB Worker thread to update the database to mark the relevant row as successfully delivered.  If the Worker gets an error, it sends a RequestFailed message to the HTTP Client actor, which at this point will just log the error and continue on.

I will have more to say about this, but this post is already decently long, so maybe I’ll leave this here so I can refer back to it later. There are a few things I’m struggling with:

  • Despite having read a lot of articles and blog posts on the subject, it’s not obvious to me what the correct way to instantiate and connect these actors is (constructor arguments, preStart() methods, dependency injection, etc).
  • Related to the above, it’s not clear to me how to test this system without mixing up test code and business logic.  In particular I’d like to replace the nodes in yellow above with mock objects and verify that the system still works properly.
  • I would like to have a reasonable interface to Oracle, without needing to include Spring or something in the project. The Typesafe, Inc solution is to use Slick, but I don’t have a burning desire to sell my co-workers on closed-source, commercial software in addition to a new language and framework. 

I’ll have more to say about all this in the days to come.