为什么这个FSM只能在一个状态转换中成功?
问题描述:
我有一个非常简单的FSM成功地做了一个过渡,但不超过。我不知道FSM中是否有错误,或者测试类是否有错误。为什么这个FSM只能在一个状态转换中成功?
这里是单元测试的完整再现的例子:
using Akka;
using Akka.Actor;
using Akka.TestKit;
using Akka.TestKit.Xunit;
using System.Diagnostics;
using Xunit;
class MyFsm : FSM<MyFsm.State, MyFsm.Data>
{
public MyFsm()
{
StartWith(State.Idle, new Data());
When(State.Idle, state =>
{
var eventWasHandled = state.FsmEvent.Match()
.With<MessageA>(message => { return; })
.WasHandled;
if (eventWasHandled)
{
Debug.WriteLine($"{State.Idle} => transitioning to {State.Busy}");
return GoTo(State.Busy);
}
else
{
Debug.WriteLine($"{State.Idle} => returning null");
return null;
}
});
When(State.Busy, state =>
{
var eventWasHandled = state.FsmEvent.Match()
.With<MessageB>(message => { return; })
.WasHandled;
if (eventWasHandled)
{
Debug.WriteLine($"{State.Busy} => transitioning to {State.Done}");
return GoTo(State.Done);
}
else
{
Debug.WriteLine($"{State.Busy} => returning null");
return null;
}
});
Initialize();
}
public enum State { Idle, Busy, Done }
public class Data { }
}
class MessageA { }
class MessageB { }
public class MyFsmTests : TestKit
{
[Fact]
public void Its_initial_state_is_Idle()
{
var myFsm = new TestFSMRef<MyFsm, MyFsm.State, MyFsm.Data>(Sys, Props.Create<MyFsm>());
Assert.Equal(MyFsm.State.Idle, myFsm.StateName);
}
[Fact]
public void It_transitions_to_the_Busy_state_after_receiving_MessageA()
{
var myFsm = new TestFSMRef<MyFsm, MyFsm.State, MyFsm.Data>(Sys, Props.Create<MyFsm>());
myFsm.SetState(MyFsm.State.Idle);
myFsm.Tell(new MessageA());
Assert.Equal(MyFsm.State.Busy, myFsm.StateName);
}
[Fact]
public void It_transitions_to_the_Done_state_after_receiving_MessageB_using_SetState()
{
var myFsm = new TestFSMRef<MyFsm, MyFsm.State, MyFsm.Data>(Sys, Props.Create<MyFsm>());
myFsm.SetState(MyFsm.State.Busy);
myFsm.Tell(new MessageB());
Assert.Equal(MyFsm.State.Done, myFsm.StateName);
}
[Fact]
public void It_transitions_to_the_Done_state_after_receiving_MessageB_without_using_SetState()
{
var myFsm = new TestFSMRef<MyFsm, MyFsm.State, MyFsm.Data>(Sys, Props.Create<MyFsm>());
myFsm.Tell(new MessageA());
myFsm.Tell(new MessageB());
Assert.Equal(MyFsm.State.Done, myFsm.StateName);
}
}
- Its_initial_state_is_Idle
- 结果:测试通过
- 输出:N/A
- It_transitions_to_the_Busy_state_after_receiving_MessageA
- 结果:测试通过
- 输出:
Idle => transitioning to Busy
- It_transitions_to_the_Done_state_after_receiving_MessageB_using_SetState
- 结果:测试失败
Assert.Equal() Failure Expected: Done Actual: Busy
- 输出:
Busy => transitioning to Done
- 结果:测试失败
- It_transitions_to_the_Done_state_after_receiving_MessageB_without_using_SetState
- 结果:测试失败
Assert.Equal() Failure Expected: Done Actual: Busy
- 输出:
Idle => transitioning to Busy
Busy => transitioning to Done
- 结果:测试失败
我已经通过文档多次了,并不能找到代码中的任何明显的错误。我错过了什么?
答
看起来这里的问题是,您实际上没有将状态定义为Done
,就此FSM知道。
您需要添加一个When(State.Done, e => { ... })
处理程序,这将允许FSM转换到该行为并正确报告。
啊,是的,这使它的工作。我在这里省略了一个处理程序,我的实际代码确实在方法中定义了一个处理程序('ConfigureFooStateHandler()'),但我忘记了在构造函数中调用此方法。 – Stijn