gpt4 book ai didi

c# - 为什么这个 FSM 只在一次状态转换中成功?

转载 作者:行者123 更新时间:2023-11-30 16:42:31 25 4
gpt4 key购买 nike

我有一个非常简单的有限状态机,可以成功完成一次转换,但仅此而已。不知道是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
    • 结果:测试通过
    • 输出:不适用
  • 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() 预期失败:完成实际:忙
    • 输出:Busy => transitioning to Done
  • It_transitions_to_the_Done_state_after_receiving_MessageB_without_using_SetState
    • 结果:测试失败 Assert.Equal() 预期失败:完成实际:忙
    • 输出:Idle => transitioning to Busy Busy => transitioning to Done

我已经多次查看文档,但在代码中找不到任何明显的错误。我错过了什么?

最佳答案

看起来这里的问题是,据此 FSM 所知,您实际上没有定义为 Done 的状态。

您需要添加一个 When(State.Done, e => { ... }) 处理程序,这将允许 FSM 转换到该行为并正确报告它。

关于c# - 为什么这个 FSM 只在一次状态转换中成功?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46588702/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com