xiangyixiangqin/server/tests/XiangYi.Application.Tests/Services/MemberServicePropertyTests.cs
2026-02-08 14:31:53 +08:00

193 lines
6.8 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
});
}
}