作爲Akka FSM的學習練習,我模擬了咖啡店的簡化訂單處理流程。附加的是狀態轉換圖。但是,我寫的一個測試用例超時了,我不明白爲什麼。爲什麼我的Akka FSM事件超時?
FSM(未示出爲了簡潔case類):
class OrderSystem extends Actor with ActorLogging with LoggingFSM[State, Data] {
startWith(OrderPending, Data(OrderPending, PaymentPending))
when(OrderPending) {
case Event(BaristaIsBusy, _) => stay
case Event(BaristaIsAvailable(_, PaymentPending), _) => goto(OrderPlaced) using Data(stateName, PaymentPending)
case Event(b: BaristaIsAvailable, _) => goto(OrderReady)
}
val waiting = Data(OrderPlaced, PaymentAccepted)
when(OrderPlaced) {
case Event(b: BaristaIsAvailable, `waiting`) => println("1"); goto(OrderReady)
case Event(b: BaristaIsBusy, `waiting`) => println("2"); goto(OrderPending) using `waiting`
case Event(_, Data(_, PaymentDeclined)) => println("3"); goto(OrderClosed)
case Event(_, Data(_, PaymentPending)) => println("4"); stay
}
when(OrderReady) {
case Event(HappyWithOrder, _) => goto(OrderClosed)
case Event(NotHappyWithOrder, _) => goto(OrderPending) using Data(stateName, PaymentAccepted)
}
when(OrderClosed) {
case _ => stay
}
whenUnhandled {
case Event(e, s) => {
// state name is available as 'stateName'
log.warning("Received unhandled request {} in state {}/{}", e, stateName, s)
stay
}
}
// previous state data is available as 'stateData' and next state data as 'nextStateData'
// not necessary as LoggingFSM (if configured) will take care of logging
onTransition {
case _ -> nextState => log.info("Entering state: {} with payment activity: {} from state: {} with payment activity: {}.",
nextState, stateData.paymentActivity, nextStateData.fromState, nextStateData.paymentActivity)
}
initialize()
}
失敗測試:
it should "stay in OrderPlaced state as long as customer has not paid" in {
val orderSystem = system.actorOf(Props[OrderSystem])
orderSystem ! BaristaIsAvailable(OrderPending, PaymentPending)
orderSystem ! SubscribeTransitionCallBack(testActor)
expectMsg(CurrentState(orderSystem, OrderPlaced))
orderSystem ! BaristaIsAvailable(OrderPlaced, PaymentPending)
expectMsg(CurrentState(orderSystem, OrderPlaced))
}
日誌:
2015-09-22 23:29:15.236 [order-system-akka.actor.default-dispatcher-2] [DEBUG] n.a.s.o.OrderSystem - processing Event(BaristaIsAvailable(OrderPending,PaymentPending),Data(OrderPending,PaymentPending)) from Actor[akka://order-system/system/testActor1#-2143558060]
2015-09-22 23:29:15.238 [order-system-akka.actor.default-dispatcher-2] [INFO ] n.a.s.o.OrderSystem - Entering state: OrderPlaced with payment activity: PaymentPending from state: OrderPending with payment activity: PaymentPending.
2015-09-22 23:29:15.239 [order-system-akka.actor.default-dispatcher-2] [DEBUG] n.a.s.o.OrderSystem - transition OrderPending -> OrderPlaced
4
2015-09-22 23:29:15.242 [order-system-akka.actor.default-dispatcher-2] [DEBUG] n.a.s.o.OrderSystem - processing Event(BaristaIsAvailable(OrderPlaced,PaymentPending),Data(OrderPending,PaymentPending)) from Actor[akka://order-system/system/testActor1#-2143558060]
[31m- should stay in OrderPlaced state as long as customer has not paid *** FAILED ***[0m
[31m java.lang.AssertionError: assertion failed: timeout (3 seconds)
你沒有發回任何回信從FSM回來,這是正常的,你expectMsg失敗 – kosii