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