3

I have an akka actor:

class MyActor extends Actor {
  def recieve { ... }

  def getCount(id: String): Int = {
    //do a lot of stuff
    proccess(id)
    //do more stuff and return
  }
}

I am trying to create a unit test for the getCount method:

it should "count" in {
    val system = ActorSystem("Test")
    val myActor = system.actorOf(Props(classOf[MyActor]), "MyActor")

    myActor.asInstanceOf[MyActor].getCount("1522021") should be >= (28000)
}

But it is not working:

  java.lang.ClassCastException: akka.actor.RepointableActorRef cannot be cast to com.playax.MyActor

How could I test this method?

Daniel Cukier
  • 11,502
  • 15
  • 68
  • 123

2 Answers2

9

Do something like this:

import org.scalatest._
import akka.actor.ActorSystem
import akka.testkit.TestActorRef
import akka.testkit.TestKit

class YourTestClassTest extends TestKit(ActorSystem("Testsystem")) with FlatSpecLike with Matchers {

  it should "count plays" in {
    val actorRef = TestActorRef(new MyActor)
    val actor = actorRef.underlyingActor
    actor.getCount("1522021") should be >= (28000)
  }
}
Daniel Cukier
  • 11,502
  • 15
  • 68
  • 123
6

I generally recommend factoring any "business logic" that is executed by an Actor into a separate class that is supplied as a constructor parameter or provided via a Cake component. Doing this simplifies the Actor, leaving it only the responsibility to protect long-lived mutable state and handle incoming messages. It also facilitates testing both the business logic (by making it separately available for unit tests) and how the Actor interacts with that logic by supplying a mock / spy instance or component when testing the Actor itself.

Randall Schulz
  • 26,420
  • 4
  • 61
  • 81
  • This is a good answer also but not always possible. For example, the overridden `persistenceId` method of my `PersistentActor` subclass. To test that method you will need the underlying actor. – Brian Ensink May 20 '16 at 14:06