JUnit @Rule for easy setup of Akka ActorSystem for tests
Java
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
src
.gitattributes
.gitignore
.travis.yml
README.md
license.txt
pom.xml

README.md

Akka Test JUNIT

Flattr this git repo Build Status Coverage Status Maven Central License: Apache 2 Libraries.io for GitHub

Provides a JUnit rule for controlled testing of Akka actors using JUnit.

Tested with Akka 2.3.15 and JUnit 4.12. This tool, including the source code is made available under an Apache 2.0 license.

Add dependency

As this library is distributed through the Sonatype OSS repository, it should be easy to add it to your project

Maven

<dependency>
    <groupId>org.zapodot</groupId>
    <artifactId>akka-test-junit</artifactId>
    <version>1.3.0</version>
    <scope>test</scope>
</dependency>

SBT

libraryDependencies += "org.zapodot" % "akka-test-junit" % "1.3.0"

Gradle

compile 'org.zapodot:akka-test-junit:1.3.0'

Example

The ActorSystemRule may be used either as a @Rule (invoked around test methods) or as a @ClassRule (invoked before/after the TestClass)

As a @Rule

public class SimpleAkkaTest {

    @Rule
    public ActorSystemRule actorSystemRule = new ActorSystemRuleBuilder().setName(getClass().getSimpleName()).build();

    @Test
    public void testRuleUsingASingleActor() throws Exception {
        final TestActorRef<SimpleActor> actorTestActorRef = TestActorRef.create(actorSystemRule.system(),
                                                                          Props.create(SimpleActor.class));
        final String message = "test";
        actorTestActorRef.tell(message, ActorRef.noSender());
        assertEquals(message, actorTestActorRef.underlyingActor().received.peek());
        
        // Use the testKit() to get an instance of JavaTestKit directly
        // In this example EchoActor simply sends the message to the designated sender actor
        final JavaTestKit testKit = actorSystemRule.testKit();
        final Props simpleActorProps = Props.create(EchoActor.class);
        final ActorRef simpleActor = actorSystemRule.system().actorOf(simpleActorProps);
        simpleActor.tell("A great message", testKit.getTestActor()); // Use testActor as sender
        testKit.expectMsgEquals(FiniteDuration.apply(1L, TimeUnit.SECONDS), "A great message");
           

    }

        
}

As a @ClassRule

public class SimpleAkkaTest {

    // ClassRules must be instantiated as public static fields on the test class
    @ClassRule
    public static ActorSystemRule actorSystemRule = ActorSystemRule.builder().setName(getClass().getSimpleName()).build();

    @Test
    public void testRuleUsingASingleActor() throws Exception {
        final TestActorRef<SimpleActor> actorTestActorRef = TestActorRef.create(actorSystemRule.system(),
                                                                          Props.create(SimpleActor.class));
        final String message = "test";
        actorTestActorRef.tell(message, ActorRef.noSender());
        assertEquals(message, actorTestActorRef.underlyingActor().received.peek());

    }
    
    @Test
    public void testAnotherThing() throws Exception {
        final TestActorRef<SimpleActor> actorTestActorRef = TestActorRef.create(actorSystemRule.system(),
                                                                                  Props.create(SimpleActor.class));
        // Will use the same actorSystem instance as in the previous test. NB! Be aware of JUnit's ordering rules                                                                         
    }
}

With event logging enabled (version >= 1.1.0)

@Rule
public ActorSystemRule actorSystemWithEventLoggerEnabled = ActorSystemRule.builder()
                                                        .enableEventLogging()
                                                        .setName(getClass().getSimpleName())
                                                        .build();

With event test listener enabled(version >= 1.1.0)

@Rule
public ActorSystemRule actorSystemRule = ActorSystemRule.builder()
                                                       .setName(getClass().getSimpleName())
                                                       .setConfigFromString("akka.loglevel = DEBUG")
                                                       .enableEventTestListener()
                                                       .build();

@Test
public void testEventFilterEnabled() throws Exception {
   new JavaTestKit(actorSystemRule.system()) {{
       final ActorRef loggingActor = getSystem().actorOf(Props.create(LoggingActor.class), "loggingActor");
       Integer result = new EventFilter<Integer>(Logging.Info.class) {
           @Override
           protected Integer run() {

               loggingActor.tell(LoggingActor.INFO_MESSAGE, ActorRef.noSender());
               return 1;
           }
       }.from(loggingActor.path().toString()).occurrences(1).exec();
       assertEquals(1, result.intValue());
   }};

}

With custom configuration (version >= 1.1.0)

public class SimpleAkkaTest {

    @Rule
    public ActorSystemRule actorSystemRule = ActorSystemRule.builder().setName("test-system").setConfigFromString(
            "akka {\n"
            + "    loggers = [\"akka.event.slf4j.Slf4jLogger\"]\n"
            + "    loglevel = DEBUG\n"
            + "}").build();

    @Test
    public void testRuleUsingASingleActor() throws Exception {
        final TestActorRef<SimpleActor> actorTestActorRef = TestActorRef.create(actorSystemRule.system(),
                                                                          Props.create(SimpleActor.class));
        final String message = "test";
        actorTestActorRef.tell(message, ActorRef.noSender());
        assertEquals(message, actorTestActorRef.underlyingActor().received.peek());

    }
}

Changelog

  • Version 1.3.0: Verifys that the ActorSystem is indeed properly shutdown. Allows a shutdown timeout to be set
  • Version 1.2.0: Add a new testKit() method that to create a JavaTestKit
  • Version 1.1.1: Fixed a bug in ActorSystemRuleBuilder that replaced the configuration instead of added to it
  • Version 1.1: Added the ActorSystemRuleBuilder and the ability to specify configuration and/or enable logging for the actor system
  • Version 1.0: First release

Limitations

A few words of caution when using @ClassRule:

  • JUnit might not run the tests in the order you predicted. Check JUnit execution ordering.
  • If you name your actors be aware the Akka expects actor names to be unique within the same actor system