using FluentAssertions; using Workflow.Domain.Enums; using Workflow.Domain.Exceptions; using Workflow.Domain.StateMachine; using Xunit; namespace Workflow.Tests.StateMachine; /// /// TokenStateMachine TDD 红灯阶段测试 /// 测试令牌状态机的所有合法转换与非法转换 /// /// 令牌状态: Active, Completed, Terminated /// 操作: NodeComplete, InstanceTerminate /// public class TokenStateMachineTests { private readonly TokenStateMachine _machine = new(); #region Active → Completed [Fact] public void Transition_Active_To_Completed_On_NodeComplete() { // Arrange - 节点执行完毕,令牌正常完成 var currentState = TokenStatus.Active; var operation = TokenOperation.NodeComplete; var context = new TokenTransitionContext(); // Act var newState = _machine.Transition(currentState, operation, context); // Assert newState.Should().Be(TokenStatus.Consumed); } #endregion #region Active → Terminated [Fact] public void Transition_Active_To_Terminated_On_InstanceTerminate() { // Arrange - 所属实例被终止,令牌随之终止 var currentState = TokenStatus.Active; var operation = TokenOperation.InstanceTerminate; var context = new TokenTransitionContext(); // Act var newState = _machine.Transition(currentState, operation, context); // Assert newState.Should().Be(TokenStatus.Terminated); } #endregion #region Illegal Transitions - Completed Is Terminal [Fact] public void Transition_Completed_To_Active_Should_Throw() { // Arrange - 已完成的令牌不能重新激活 var currentState = TokenStatus.Consumed; var operation = TokenOperation.NodeComplete; var context = new TokenTransitionContext(); // Act var act = () => _machine.Transition(currentState, operation, context); // Assert act.Should().Throw(); } [Fact] public void Transition_Completed_To_Terminated_Should_Throw() { // Arrange - 已完成的令牌不能再终止 var currentState = TokenStatus.Consumed; var operation = TokenOperation.InstanceTerminate; var context = new TokenTransitionContext(); // Act var act = () => _machine.Transition(currentState, operation, context); // Assert act.Should().Throw(); } #endregion #region Illegal Transitions - Terminated Is Terminal [Fact] public void Transition_Terminated_To_Active_Should_Throw() { // Arrange - 已终止的令牌不能重新激活 var currentState = TokenStatus.Terminated; var operation = TokenOperation.NodeComplete; var context = new TokenTransitionContext(); // Act var act = () => _machine.Transition(currentState, operation, context); // Assert act.Should().Throw(); } [Fact] public void Transition_Terminated_To_Completed_Should_Throw() { // Arrange - 已终止的令牌不能变为完成 var currentState = TokenStatus.Terminated; var operation = TokenOperation.NodeComplete; var context = new TokenTransitionContext(); // Act var act = () => _machine.Transition(currentState, operation, context); // Assert act.Should().Throw(); } #endregion #region Illegal Transitions - Active State Restrictions [Fact] public void Transition_Active_NodeComplete_Twice_Should_Throw_On_Second_Call() { // Arrange - 模拟令牌已完成后再尝试完成 // 第一次转换成功 var firstState = _machine.Transition(TokenStatus.Active, TokenOperation.NodeComplete, new TokenTransitionContext()); firstState.Should().Be(TokenStatus.Consumed); // Act - 第二次从 Completed 状态再尝试完成 var act = () => _machine.Transition(firstState, TokenOperation.NodeComplete, new TokenTransitionContext()); // Assert act.Should().Throw(); } [Fact] public void Transition_Active_InstanceTerminate_Twice_Should_Throw_On_Second_Call() { // Arrange - 模拟令牌已终止后再尝试终止 var firstState = _machine.Transition(TokenStatus.Active, TokenOperation.InstanceTerminate, new TokenTransitionContext()); firstState.Should().Be(TokenStatus.Terminated); // Act - 第二次从 Terminated 状态再尝试终止 var act = () => _machine.Transition(firstState, TokenOperation.InstanceTerminate, new TokenTransitionContext()); // Assert act.Should().Throw(); } #endregion }