我有一个在州内使用期货的akka FSM演员。例如:
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
}
使用akka testkit测试上面的actor:
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)
}
}
您可以在github上找到的测试的完整代码:https://github.com/azhur/fsmtest
问题是测试随机失败(有时它们都通过了)。
测试中出现失败“应该返回await-ping
” - &gt; “AwaitStateA不等于StateA”。
请帮忙找出我弄错的地方。
我尝试从命令行和IDE(Intellij IDEA)运行测试。结果是一样的。当我单独运行每个测试时,很难发现故障。
答案 0 :(得分:2)
未来正在全局ExecutionContext(您已导入)上运行,并且它与TestFSMRef使用的调用线程调度程序之间存在竞争。
我不会在这里使用TestFSMRef。如果验证状态转换很重要,则可以使用FSM转换侦听器。像这样:
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))
}