Question

I have an akka FSM actor which uses futures in states. For example:

when(StateA) {
  case Event(str: String, _) =>
    if (str == "ping") {
      Future("await-ping").pipeTo(self)(sender)
      goto(AwaitStateA)
    } else {
      stay() replying "stay-ping"
    }
}

when(AwaitStateA) {
  case Event(str: String, _) =>
  goto(StateA) replying str
}

Tests for actor above using akka testkit:

val adaptation: TestFSMRef[State, Data, _ <: Actor]

"Switch between states A" must {
  "should return `await-ping`" in {
    adaptation ! "ping"
    expectMsg("await-ping")
    adaptation.stateName should be(StateA)
  }
  "should return `stay-ping`" in {
    adaptation ! "pong"
    expectMsg("stay-ping")
    adaptation.stateName should be(StateA)
  }
}

Full code for tests you can find on github: https://github.com/azhur/fsmtest

The Problem is that tests failed randomly (sometimes they all passed). Failures appear in test "should return await-ping" -> "AwaitStateA was not equal to StateA". Please help to find where am I mistaken.

I try to run tests from command line and from IDE (Intellij IDEA). Results are the same. When I run each test separately, is hard to catch failure.

Was it helpful?

Solution

The future is running on the global ExecutionContext (that you have imported) and there is a race between that and the calling thread dispatcher that is used by TestFSMRef.

I would not use TestFSMRef here. If it is important to verify the state transitions you can use the FSM transition listener instead. Something like this:

val adaptation: ActorRef = system.actorOf(Props[FsmSwitcher1])

"should return `await-ping`" in {
  val transitionListener = TestProbe()
  adaptation ! SubscribeTransitionCallBack(transitionListener.ref)
  transitionListener.expectMsg(CurrentState(adaptation, StateA))
  adaptation ! "ping"
  expectMsg("await-ping")
  transitionListener.expectMsg(Transition(adaptation, StateA, AwaitStateA))
  transitionListener.expectMsg(Transition(adaptation, AwaitStateA, StateA))
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top