159 lines
4.8 KiB
C#
159 lines
4.8 KiB
C#
using FluentAssertions;
|
|
using Workflow.Domain.Enums;
|
|
using Workflow.Domain.Exceptions;
|
|
using Workflow.Domain.StateMachine;
|
|
using Xunit;
|
|
|
|
namespace Workflow.Tests.StateMachine;
|
|
|
|
/// <summary>
|
|
/// TokenStateMachine TDD 红灯阶段测试
|
|
/// 测试令牌状态机的所有合法转换与非法转换
|
|
///
|
|
/// 令牌状态: Active, Completed, Terminated
|
|
/// 操作: NodeComplete, InstanceTerminate
|
|
/// </summary>
|
|
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<InvalidStateTransitionException>();
|
|
}
|
|
|
|
[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<InvalidStateTransitionException>();
|
|
}
|
|
|
|
#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<InvalidStateTransitionException>();
|
|
}
|
|
|
|
[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<InvalidStateTransitionException>();
|
|
}
|
|
|
|
#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<InvalidStateTransitionException>();
|
|
}
|
|
|
|
[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<InvalidStateTransitionException>();
|
|
}
|
|
|
|
#endregion
|
|
}
|