using FsCheck; using FsCheck.Xunit; using Xunit; using XiangYi.Application.Interfaces; using XiangYi.Application.Services; namespace XiangYi.Application.Tests.Services; /// /// MemberService属性测试 - 家庭版绑定数量限制 /// public class FamilyBindLimitPropertyTests { /// /// **Feature: backend-api, Property 18: 家庭版绑定数量限制** /// **Validates: Requirements 7.3** /// /// *For any* 家庭版会员绑定操作, 绑定用户数量不应超过2个(不含主账号) /// [Property(MaxTest = 100)] public Property FamilyBind_ShouldNotExceedMaxLimit() { // 生成当前绑定数量(0-5,包含超出限制的情况) var currentBindCountArb = Gen.Choose(0, 5); return Prop.ForAll( currentBindCountArb.ToArbitrary(), currentBindCount => { // Arrange var maxBindCount = IMemberService.MaxFamilyBindCount; // 2 // Act var canBind = MemberService.CanBindFamilyMember(currentBindCount, maxBindCount); var countAfterBind = MemberService.CalculateFamilyBindCountAfterBind(currentBindCount, maxBindCount); // Assert if (currentBindCount >= maxBindCount) { // 已达到或超过限制,不能再绑定 return !canBind && countAfterBind == -1; } else { // 未达到限制,可以绑定,绑定后数量+1 return canBind && countAfterBind == currentBindCount + 1; } }); } /// /// 家庭版绑定 - 绑定后数量不应超过最大限制 /// [Property(MaxTest = 100)] public Property FamilyBind_CountAfterBind_ShouldNotExceedMax() { var currentBindCountArb = Gen.Choose(0, IMemberService.MaxFamilyBindCount - 1); return Prop.ForAll( currentBindCountArb.ToArbitrary(), currentBindCount => { var maxBindCount = IMemberService.MaxFamilyBindCount; var countAfterBind = MemberService.CalculateFamilyBindCountAfterBind(currentBindCount, maxBindCount); // 绑定后数量应该不超过最大限制 return countAfterBind <= maxBindCount; }); } /// /// 家庭版绑定 - 达到限制时应拒绝绑定 /// [Property(MaxTest = 100)] public Property FamilyBind_AtMaxLimit_ShouldReject() { return Prop.ForAll( Arb.Default.PositiveInt(), _ => { var maxBindCount = IMemberService.MaxFamilyBindCount; var currentBindCount = maxBindCount; // 已达到最大限制 var canBind = MemberService.CanBindFamilyMember(currentBindCount, maxBindCount); var countAfterBind = MemberService.CalculateFamilyBindCountAfterBind(currentBindCount, maxBindCount); // 达到限制时应该拒绝绑定 return !canBind && countAfterBind == -1; }); } /// /// 家庭版绑定 - 超过限制时应拒绝绑定 /// [Property(MaxTest = 100)] public Property FamilyBind_OverMaxLimit_ShouldReject() { // 生成超过限制的数量 var overLimitCountArb = Gen.Choose(IMemberService.MaxFamilyBindCount + 1, 10); return Prop.ForAll( overLimitCountArb.ToArbitrary(), currentBindCount => { var maxBindCount = IMemberService.MaxFamilyBindCount; var canBind = MemberService.CanBindFamilyMember(currentBindCount, maxBindCount); var countAfterBind = MemberService.CalculateFamilyBindCountAfterBind(currentBindCount, maxBindCount); // 超过限制时应该拒绝绑定 return !canBind && countAfterBind == -1; }); } /// /// 家庭版绑定 - 从0开始绑定应该成功 /// [Property(MaxTest = 100)] public Property FamilyBind_FromZero_ShouldSucceed() { return Prop.ForAll( Arb.Default.PositiveInt(), _ => { var maxBindCount = IMemberService.MaxFamilyBindCount; var currentBindCount = 0; var canBind = MemberService.CanBindFamilyMember(currentBindCount, maxBindCount); var countAfterBind = MemberService.CalculateFamilyBindCountAfterBind(currentBindCount, maxBindCount); // 从0开始应该可以绑定 return canBind && countAfterBind == 1; }); } /// /// 家庭版绑定 - 每次绑定应该正好增加1 /// [Property(MaxTest = 100)] public Property FamilyBind_ShouldIncrementByOne() { var validBindCountArb = Gen.Choose(0, IMemberService.MaxFamilyBindCount - 1); return Prop.ForAll( validBindCountArb.ToArbitrary(), currentBindCount => { var maxBindCount = IMemberService.MaxFamilyBindCount; var countAfterBind = MemberService.CalculateFamilyBindCountAfterBind(currentBindCount, maxBindCount); // 绑定后应该正好增加1 return countAfterBind == currentBindCount + 1; }); } /// /// 家庭版绑定 - 最大绑定数量应该是2 /// [Fact] public void FamilyBind_MaxBindCount_ShouldBeThree() { Assert.Equal(2, IMemberService.MaxFamilyBindCount); } /// /// 家庭版绑定 - 绑定1个后还能再绑定1个 /// [Property(MaxTest = 100)] public Property FamilyBind_AfterBindingOne_CanBindOneMore() { return Prop.ForAll( Arb.Default.PositiveInt(), _ => { var maxBindCount = IMemberService.MaxFamilyBindCount; // 绑定第一个 var countAfterFirst = MemberService.CalculateFamilyBindCountAfterBind(0, maxBindCount); var canBindSecond = MemberService.CanBindFamilyMember(countAfterFirst, maxBindCount); // 绑定第二个 var countAfterSecond = MemberService.CalculateFamilyBindCountAfterBind(countAfterFirst, maxBindCount); var canBindThird = MemberService.CanBindFamilyMember(countAfterSecond, maxBindCount); // 绑定1个后应该还能绑定1个,但绑定2个后不能再绑定 return countAfterFirst == 1 && canBindSecond && countAfterSecond == 2 && !canBindThird; }); } }