193 lines
6.8 KiB
C#
193 lines
6.8 KiB
C#
using FsCheck;
|
||
using FsCheck.Xunit;
|
||
using Xunit;
|
||
using XiangYi.Application.Interfaces;
|
||
using XiangYi.Application.Services;
|
||
|
||
namespace XiangYi.Application.Tests.Services;
|
||
|
||
/// <summary>
|
||
/// MemberService属性测试 - 家庭版绑定数量限制
|
||
/// </summary>
|
||
public class FamilyBindLimitPropertyTests
|
||
{
|
||
/// <summary>
|
||
/// **Feature: backend-api, Property 18: 家庭版绑定数量限制**
|
||
/// **Validates: Requirements 7.3**
|
||
///
|
||
/// *For any* 家庭版会员绑定操作, 绑定用户数量不应超过2个(不含主账号)
|
||
/// </summary>
|
||
[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;
|
||
}
|
||
});
|
||
}
|
||
|
||
/// <summary>
|
||
/// 家庭版绑定 - 绑定后数量不应超过最大限制
|
||
/// </summary>
|
||
[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;
|
||
});
|
||
}
|
||
|
||
/// <summary>
|
||
/// 家庭版绑定 - 达到限制时应拒绝绑定
|
||
/// </summary>
|
||
[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;
|
||
});
|
||
}
|
||
|
||
/// <summary>
|
||
/// 家庭版绑定 - 超过限制时应拒绝绑定
|
||
/// </summary>
|
||
[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;
|
||
});
|
||
}
|
||
|
||
/// <summary>
|
||
/// 家庭版绑定 - 从0开始绑定应该成功
|
||
/// </summary>
|
||
[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;
|
||
});
|
||
}
|
||
|
||
/// <summary>
|
||
/// 家庭版绑定 - 每次绑定应该正好增加1
|
||
/// </summary>
|
||
[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;
|
||
});
|
||
}
|
||
|
||
/// <summary>
|
||
/// 家庭版绑定 - 最大绑定数量应该是2
|
||
/// </summary>
|
||
[Fact]
|
||
public void FamilyBind_MaxBindCount_ShouldBeThree()
|
||
{
|
||
Assert.Equal(2, IMemberService.MaxFamilyBindCount);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 家庭版绑定 - 绑定1个后还能再绑定1个
|
||
/// </summary>
|
||
[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;
|
||
});
|
||
}
|
||
}
|