其他系列博文
- 基于Abp的扩展模块实现 - 前言
- 基于Abp的扩展模块实现第1例 - 数据权限控制(开发)
- 基于Abp的扩展模块实现第1例 - 数据权限控制(测试)
- 基于Abp的扩展模块实现第2例 - 数据字段按需更新(开发)
- 基于Abp的扩展模块实现第2例 - 数据字段按需更新(测试)
- 基于Abp的扩展模块实现第3例 - 状态管理(开发)
背景
在上一篇博文中,我们建立了状态切换/处理与源状态/目标状态的解耦,实现了一个基于Abp的状态管理模块,在这一篇中博主将对该机制编写单元测试。
目标
- 对状态定义与状态处理两个核心功能进行测试。
思路
在创建测试状态类时,覆盖以下情形:
- 父子状态层次结构
- 状态切换分支
- 多对多切换
编码
创建测试状态定义类
TestStateDefinitionProvider
,与状态名称静态类TestStateNames
:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75public class TestStateDefinitionProvider : StateDefinitionProvider
{
public override void Define(IStateDefinitionContext context)
{
var deviceGroup = context
.AddGroup(TestStateNames.RootGroup)
.AddGroup(TestStateNames.DeviceGroup);
var onlineGroup = deviceGroup.AddGroup(TestStateNames.OnlineGroup);
var normalGroup = onlineGroup.AddGroup(TestStateNames.NormalGroup);
var faultGroup = onlineGroup.AddGroup(TestStateNames.FaultGroup);
var normalOpenState = normalGroup.AddState(TestStateNames.NormalOpenState);
var normalCloseState = normalGroup.AddState(TestStateNames.NormalCloseState);
var faultOpenState = faultGroup.AddState(TestStateNames.FaultOpenState);
var faultCloseState = faultGroup.AddState(TestStateNames.FaultCloseState);
var offlineState = deviceGroup.AddState(TestStateNames.OfflineState);
onlineGroup
.On(TestStateNames.OfflineTerm)
.TransitTo(offlineState);
offlineState
.On(TestStateNames.NormalCloseTerm)
.TransitTo(normalCloseState)
.On(TestStateNames.FaultCloseTerm)
.TransitTo(faultCloseState)
.On(TestStateNames.NormalOpenTerm)
.TransitTo(normalOpenState)
.On(TestStateNames.FaultOpenTerm)
.TransitTo(faultOpenState);
normalOpenState
.On(TestStateNames.NormalCloseTerm)
.TransitTo(normalCloseState)
.ReverseOn(TestStateNames.NormalOpenTerm)
.On(TestStateNames.FaultOpenTerm)
.TransitTo(faultOpenState)
.ReverseOn(TestStateNames.NormalOpenTerm);
normalCloseState
.On(TestStateNames.FaultCloseTerm)
.TransitTo(faultCloseState)
.ReverseOn(TestStateNames.NormalCloseTerm);
faultOpenState
.On(TestStateNames.FaultCloseTerm)
.TransitTo(faultCloseState)
.ReverseOn(TestStateNames.FaultOpenTerm);
}
}
public static class TestStateNames
{
public const string RootGroup = "Root";
public const string DeviceGroup = "Device";
public const string OnlineGroup = DeviceGroup + ".Online";
public const string NormalGroup = OnlineGroup + ".Normal";
public const string FaultGroup = OnlineGroup + ".Fault";
public const string NormalOpenState = NormalGroup + ".Open";
public const string NormalCloseState = NormalGroup + ".Close";
public const string FaultOpenState = FaultGroup + ".Open";
public const string FaultCloseState = FaultGroup + ".Close";
public const string OfflineState = DeviceGroup + ".Offline";
public const string OfflineTerm = "Offline";
public const string NormalOpenTerm = "NormalOpen";
public const string NormalCloseTerm = "NormalClose";
public const string FaultOpenTerm = "FaultOpen";
public const string FaultCloseTerm = "FaultClose";
}创建测试类
StatesDefinition_Tests
测试状态定义功能:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52public class StatesDefinition_Tests : StatesTestBase
{
private readonly IStateDefinitionManager _stateDefinitionManager;
private readonly IConfiguration _configuration;
public StatesDefinition_Tests()
{
_stateDefinitionManager = GetRequiredService<IStateDefinitionManager>();
_configuration = GetRequiredService<IConfiguration>();
}
[ ]
public void Should_Register_States_Using_Provider()
{
var deviceGroup = _stateDefinitionManager.GetGroupRecursivelyOrNull(TestStateNames.DeviceGroup);
var onlineGroup = _stateDefinitionManager.GetGroupRecursivelyOrNull(TestStateNames.OnlineGroup);
var normalGroup = _stateDefinitionManager.GetGroupRecursivelyOrNull(TestStateNames.NormalGroup);
var faultGroup = _stateDefinitionManager.GetGroupRecursivelyOrNull(TestStateNames.FaultGroup);
deviceGroup.ShouldNotBeNull();
onlineGroup.ShouldNotBeNull();
normalGroup.ShouldNotBeNull();
faultGroup.ShouldNotBeNull();
deviceGroup.States.Count.ShouldBe(1);
onlineGroup.States.Count.ShouldBe(0);
normalGroup.States.Count.ShouldBe(2);
faultGroup.States.Count.ShouldBe(2);
onlineGroup.GetAllStates().Count.ShouldBe(4);
deviceGroup.States.SelectMany(state => state.Transitions).Count().ShouldBe(4);
normalGroup.States.SelectMany(state => state.Transitions).Count().ShouldBe(6);
faultGroup.States.SelectMany(state => state.Transitions).Count().ShouldBe(6);
}
[ ]
public void Should_Get_Correct_Group_Belongings()
{
_stateDefinitionManager.IsGroupBelongTo(TestStateNames.OnlineGroup, TestStateNames.DeviceGroup).ShouldBeTrue();
_stateDefinitionManager.IsGroupBelongTo(TestStateNames.NormalGroup, TestStateNames.DeviceGroup).ShouldBeTrue();
_stateDefinitionManager.IsGroupBelongTo(TestStateNames.OnlineGroup, TestStateNames.NormalGroup).ShouldBeFalse();
_stateDefinitionManager.IsGroupBelongTo(TestStateNames.OnlineGroup, TestStateNames.OnlineGroup).ShouldBeTrue();
_stateDefinitionManager.IsGroupBelongTo(TestStateNames.OnlineGroup, TestStateNames.OnlineGroup, false).ShouldBeFalse();
}
[ ]
public void Should_Read_State_Definition_From_Configuration()
{
var configuration = _configuration;
}
}创建测试类
StatesHandler_Tests
测试状态切换处理功能:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41public class StatesHandler_Tests : StatesTestBase
{
private readonly IStateTransitionNotifier _stateTransitionNotifier;
private readonly Func<IDictionary<StateTransitionDefinition, bool>, string> _postHandleAction;
private readonly Action<StateTransitionContext> _contextAction;
public StatesHandler_Tests()
{
_stateTransitionNotifier = GetRequiredService<IStateTransitionNotifier>();
_postHandleAction = handlerContext => handlerContext.Values.Where(value => value).Count().ToString();
_contextAction = context => context.SetProperty(TestStateTransitionHandlerBase.PostHandleActionKey, _postHandleAction);
}
[ ]
public async Task Should_Notify_Within_Given_Group_By_Default()
{
await _stateTransitionNotifier.NotifyAsync(TestStateNames.DeviceGroup, TestStateNames.NormalCloseTerm, _contextAction);
RecordLatestStateTransitionHandler.LatestTransition.Count.ShouldBe(3);
RecordLatestStateTransitionHandler.HandleResult.ShouldBe("3");
await _stateTransitionNotifier.NotifyAsync(TestStateNames.NormalGroup, TestStateNames.NormalCloseTerm, _contextAction);
RecordLatestStateTransitionHandler.LatestTransition.Count.ShouldBe(1);
RecordLatestStateTransitionHandler.HandleResult.ShouldBe("1");
}
[ ]
public async Task Should_Break_When_All_Transitions_Are_Handled_By_Default()
{
await _stateTransitionNotifier.NotifyAsync(TestStateNames.DeviceGroup, TestStateNames.NormalCloseTerm, _contextAction);
UnReachableStateTransitionHandler.HandleResult.ShouldBeNull();
}
[ ]
public async Task Should_Not_Handle_If_Notified_Group_Is_Larger()
{
await _stateTransitionNotifier.NotifyAsync(TestStateNames.RootGroup, TestStateNames.NormalCloseTerm, _contextAction);
RecordLatestStateTransitionHandler.LatestTransition.Count.ShouldBe(0);
RecordLatestStateTransitionHandler.HandleResult.ShouldBeNull();
}
}测试写完了,我们来跑一下:
完美通过。
至此状态管理模块的开发与测试已全部完毕。