using FsCheck;
using FsCheck.Xunit;
using Xunit;
using XiangYi.Application.Services;
using XiangYi.Core.Entities.Biz;
using XiangYi.Core.Enums;
namespace XiangYi.Application.Tests.Services;
///
/// ReportService属性测试 - 举报记录完整性
///
public class ReportCompletenessPropertyTests
{
// 预定义的举报原因列表
private static readonly string[] ValidReasons = new[]
{
"虚假信息", "骚扰行为", "不当言论", "欺诈行为", "色情内容", "广告推销"
};
// 预定义的有效举报类型
private static readonly int[] ValidReportTypes = new[]
{
(int)ReportType.User, (int)ReportType.Message, (int)ReportType.Profile
};
///
/// **Feature: backend-api, Property 26: 举报记录完整性**
/// **Validates: Requirements 16.1**
///
/// *For any* 创建的举报记录, 应包含举报人、被举报人、举报原因、举报时间等必要字段
///
[Property(MaxTest = 100)]
public Property Report_ShouldHaveAllRequiredFields()
{
return Prop.ForAll(
Arb.Default.PositiveInt(),
positiveInt =>
{
// 使用随机数生成不同的测试数据
var seed = positiveInt.Get;
var reporterId = (seed % 500) + 1;
var reportedUserId = ((seed % 500) + 501);
var reportType = ValidReportTypes[seed % ValidReportTypes.Length];
var reason = ValidReasons[seed % ValidReasons.Length];
// Act - 创建举报记录
var report = ReportService.CreateReportStatic(
reporterId,
reportedUserId,
reportType,
reason,
description: null,
evidenceUrls: null);
// Assert - 验证所有必要字段都存在
var hasRequiredFields = ReportService.HasRequiredFields(report);
// 验证具体字段
var hasReporterId = report.ReporterId == reporterId;
var hasReportedUserId = report.ReportedUserId == reportedUserId;
var hasReportType = report.ReportType == reportType;
var hasReason = report.Reason == reason;
var hasCreateTime = report.CreateTime != default;
var hasStatus = report.Status == (int)ReportStatus.Pending;
return hasRequiredFields
&& hasReporterId
&& hasReportedUserId
&& hasReportType
&& hasReason
&& hasCreateTime
&& hasStatus;
});
}
///
/// 举报记录 - 举报人和被举报人不能相同
///
[Property(MaxTest = 100)]
public Property Report_ReporterAndReportedUser_ShouldBeDifferent()
{
return Prop.ForAll(
Arb.Default.PositiveInt(),
positiveInt =>
{
var userId = positiveInt.Get;
var reportType = ValidReportTypes[userId % ValidReportTypes.Length];
var reason = ValidReasons[userId % ValidReasons.Length];
// 当举报人和被举报人相同时,验证应该失败
var isValid = ReportService.ValidateReportCompleteness(
userId,
userId, // 相同的用户ID
reportType,
reason,
DateTime.Now);
// 应该返回false,因为不能举报自己
return !isValid;
});
}
///
/// 举报记录 - 举报原因不能为空
///
[Property(MaxTest = 100)]
public Property Report_Reason_ShouldNotBeEmpty()
{
return Prop.ForAll(
Arb.Default.PositiveInt(),
positiveInt =>
{
var seed = positiveInt.Get;
var reporterId = (seed % 500) + 1;
var reportedUserId = ((seed % 500) + 501);
var reportType = ValidReportTypes[seed % ValidReportTypes.Length];
// 测试空字符串
var emptyReasons = new[] { "", " ", " " };
var emptyReason = emptyReasons[seed % emptyReasons.Length];
// 当举报原因为空时,验证应该失败
var isValid = ReportService.ValidateReportCompleteness(
reporterId,
reportedUserId,
reportType,
emptyReason,
DateTime.Now);
// 应该返回false,因为举报原因不能为空
return !isValid;
});
}
///
/// 举报记录 - 举报类型必须有效
///
[Property(MaxTest = 100)]
public Property Report_Type_ShouldBeValid()
{
return Prop.ForAll(
Arb.Default.PositiveInt(),
positiveInt =>
{
var seed = positiveInt.Get;
var reporterId = (seed % 500) + 1;
var reportedUserId = ((seed % 500) + 501);
var reportType = ValidReportTypes[seed % ValidReportTypes.Length];
var reason = ValidReasons[seed % ValidReasons.Length];
// 有效的举报类型应该通过验证
var isValid = ReportService.ValidateReportCompleteness(
reporterId,
reportedUserId,
reportType,
reason,
DateTime.Now);
return isValid;
});
}
///
/// 举报记录 - 无效的举报类型应该被拒绝
///
[Property(MaxTest = 100)]
public Property Report_InvalidType_ShouldBeRejected()
{
return Prop.ForAll(
Arb.Default.PositiveInt(),
positiveInt =>
{
var seed = positiveInt.Get;
var reporterId = (seed % 500) + 1;
var reportedUserId = ((seed % 500) + 501);
// 生成无效的举报类型(不在枚举范围内)
var invalidReportTypes = new[] { 0, -1, 4, 5, 100 };
var invalidReportType = invalidReportTypes[seed % invalidReportTypes.Length];
var reason = ValidReasons[seed % ValidReasons.Length];
// 无效的举报类型应该验证失败
var isValid = ReportService.ValidateReportCompleteness(
reporterId,
reportedUserId,
invalidReportType,
reason,
DateTime.Now);
// 应该返回false
return !isValid;
});
}
///
/// 举报记录 - 证据保存正确性
///
[Property(MaxTest = 100)]
public Property Report_Evidence_ShouldBePreserved()
{
return Prop.ForAll(
Arb.Default.PositiveInt(),
positiveInt =>
{
var seed = positiveInt.Get;
var reporterId = (seed % 500) + 1;
var reportedUserId = ((seed % 500) + 501);
var reportType = ValidReportTypes[seed % ValidReportTypes.Length];
var reason = ValidReasons[seed % ValidReasons.Length];
var evidenceCount = (seed % 5) + 1; // 1-5个证据
// 生成证据URL列表
var evidenceUrls = Enumerable.Range(1, evidenceCount)
.Select(i => $"https://example.com/evidence_{i}.jpg")
.ToList();
// Act - 创建带证据的举报记录
var report = ReportService.CreateReportStatic(
reporterId,
reportedUserId,
reportType,
reason,
description: "详细描述",
evidenceUrls: evidenceUrls);
// Assert - 验证证据被正确保存
var hasEvidence = !string.IsNullOrEmpty(report.Evidence);
var evidenceContainsUrls = evidenceUrls.All(url => report.Evidence!.Contains(url));
return hasEvidence && evidenceContainsUrls;
});
}
///
/// 举报记录 - 创建时间应该是当前时间附近
///
[Property(MaxTest = 100)]
public Property Report_CreateTime_ShouldBeRecent()
{
return Prop.ForAll(
Arb.Default.PositiveInt(),
positiveInt =>
{
var seed = positiveInt.Get;
var reporterId = (seed % 500) + 1;
var reportedUserId = ((seed % 500) + 501);
var reportType = ValidReportTypes[seed % ValidReportTypes.Length];
var reason = ValidReasons[seed % ValidReasons.Length];
var beforeCreate = DateTime.Now;
// Act - 创建举报记录
var report = ReportService.CreateReportStatic(
reporterId,
reportedUserId,
reportType,
reason,
description: null,
evidenceUrls: null);
var afterCreate = DateTime.Now;
// Assert - 创建时间应该在beforeCreate和afterCreate之间
return report.CreateTime >= beforeCreate && report.CreateTime <= afterCreate;
});
}
///
/// 举报记录 - 初始状态应该是待处理
///
[Property(MaxTest = 100)]
public Property Report_InitialStatus_ShouldBePending()
{
return Prop.ForAll(
Arb.Default.PositiveInt(),
positiveInt =>
{
var seed = positiveInt.Get;
var reporterId = (seed % 500) + 1;
var reportedUserId = ((seed % 500) + 501);
var reportType = ValidReportTypes[seed % ValidReportTypes.Length];
var reason = ValidReasons[seed % ValidReasons.Length];
// Act - 创建举报记录
var report = ReportService.CreateReportStatic(
reporterId,
reportedUserId,
reportType,
reason,
description: null,
evidenceUrls: null);
// Assert - 初始状态应该是待处理
return report.Status == (int)ReportStatus.Pending;
});
}
}