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]
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 Actor
s 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.