Question

I am trying to test an Akka FSM using the information provided here. However I cannot figure out how to create a TestFSMRef when my subclass of Actor with FSM requires parameters for instantiation.

For standard, non-FSM tests, I create the TestActorRef via:

val testActor = TestActorRef(MyActorFSM.props("nl", p1, p2))

where the .props method is implemented as per the documented Recommended Practice. I have tried instantiating a testActor and then passing that to the TestFSMRef constructor:

val fsm = TestFSMRef(testActor)

but that does not compile:

inferred type arguments [Nothing,Nothing,akka.testkit.TestActorRef[Nothing]]
do not conform to method apply's type parameter bounds [S,D,T <: akka.actor.Actor]
Was it helpful?

Solution

Stealing the code from akka's example FSM actor, I tweaked it a bit to have two constructor params and it now looks like this:

class MyFSMActor(foo:String, bar:Int) extends Actor with FSM[State,Data]{
  println(s"My foo = $foo and my bar = $bar")
  startWith(Idle, Uninitialized)

  when(Idle) {
    case Event(SetTarget(ref), Uninitialized) =>
      stay using Todo(ref, Vector.empty)
  }

  // transition elided ...

  when(Active, stateTimeout = 1 second) {
    case Event(Flush | StateTimeout, t: Todo) =>
      goto(Idle) using t.copy(queue = Vector.empty)
  }

  // unhandled elided ...

  initialize()
}

Then, I can create a test ref to it like so:

val test = TestFSMRef(new MyFSMActor("hello", 1))
println(test.stateName)

When I do that, I see:

My foo = hello and my bar = 1
Idle

You normally don't invoke the Actors constructor directly (and it will fail if you do), but wrapping it in a TestActorRef or a TestFSMRef will allow you to get around that limitation. I hope this helps you get your code working.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top