How to Unit Test Akka.NET Actors with Akka.TestKit

An Introduction to the Akka.TestKit

In this post we introduce the Akka.TestKit module - a library that makes it easy to unit test Akka.NET actors using all of the popular .NET unit testing frameworks.

A Brief End-to-End Akka.TestKit Example

Before going deep into the TestKit, here’s an end-to-end example of what a test usually looks like.

[TestFixture] //using NUnit
public class UserIdentityActorSpecs : TestKit{

    [Test]
    public void UserIdentityActor_should_confirm_user_creation_success()
    {
        var identity = Sys.ActorOf(Props.Create(() => new UserIdentityActor()));
        identity.Tell(new UserIdentityActor.CreateUserWithValidUserInfo());
        var result = ExpectMsg<UserIdentityActor.OperationResult>().Successful;
        Assert.True(result);
    }

}

80% of your tests will be this simple: create an actor, send it a message, and expect a response back. Let’s explore how to do it.

The concepts in this post were first introduced in a talk at the 2015 Cassandra Summit.

I’ve been a .NET developer for roughly 10 years now - since the summer after my freshman year in college in 2005 I’ve been developing in Visual Studio and .NET. I’ve founded three startups on .NET, worked for Microsoft, and founded multiple successful OSS projects in .NET - I say all of this in evidence to the depth of my commitment and investment in the .NET ecosystem.

But it’s time we, the .NET community, address a major elephant in the room - .NET is, and often has been, way behind in other ecosystems in terms of overall innovation, openness to new ideas, and flexibility.

The Experience of Being a .NET Developer

.NET has been, historically, an expensive ecosystem to play in.

Because to play in it, you have to do so by Microsoft’s rules.

It's Ballmer's World, Bro

  • You have to buy a license for Visual Studio, or more likely, an MSDN subscription.
  • You have to buy a license for Windows Server.
  • You have to buy a license for Windows Server.
  • You have to develop your web applications in a framework built by Microsoft, like ASP.NET or WCF.
  • You have to host your web applications in IIS.

And the list goes on - the point being that our entire way of developing our own products depends on a single company in Redmond choosing what tools it wants to make available to us at any given time and price.

The Impact of Marrying .NET to Microsoft

I want to share with you a little story from a point in my career with Microsoft during 2010-2011. By 2011 HTML5 had become mostly standardized and its...

Stopping an actor is a routine operation that developers often find confusing. This is because each actor is like a micro process, and all interaction with an actor is asynchronous. So shutting down an actor is more complex than stopping entities in procedural code.

In this post, I’m going to review one of the common questions that I’ve heard lately:

How do I stop an actor?!

The Ways of Stopping an Actor

In short, there are three ways to stop an actor:

  1. Stop() the actor: stops the actor immediately after it finishes processing the current message.
  2. Kill the actor: this throws an ActorKilledException which will be logged and handled. The actor will stop immediately after it finishes processing the current message.
  3. Send the actor a PoisonPill: the actor will finish processing the messages currently in its mailbox, and then Stop.

Now let’s go over each in detail.

1) The Default: Stop() an Actor

This is the go-to method to stop an actor, and should be your default approach.

What Happens When I Stop() an Actor?

This is the sequence of events when you Stop() an actor:

  1. Actor receives the Stop message and suspends the actor’s Mailbox.
  2. Actor tells all its children to Stop. Stop messages propagate down the hierarchy below the actor.
  3. Actor waits for all children to stop.
  4. Actor calls PostStop lifecycle hook method for resource cleanup.
  5. Actor shuts down.

The point of this sequence is to make sure that an actor—and any hierarchy beneath it—have a clean shut down.

How Do I Use Stop()?

You Stop() an actor via the ActorContext, like this:

// targetActorRef dies immediately...