873 lines
33 KiB
C#
873 lines
33 KiB
C#
using FsCheck;
|
||
using FsCheck.Xunit;
|
||
using Microsoft.EntityFrameworkCore;
|
||
using Microsoft.Extensions.Logging;
|
||
using MiAssessment.Admin.Business.Data;
|
||
using MiAssessment.Admin.Business.Entities;
|
||
using MiAssessment.Admin.Business.Models;
|
||
using MiAssessment.Admin.Business.Models.BusinessPage;
|
||
using MiAssessment.Admin.Business.Models.Common;
|
||
using MiAssessment.Admin.Business.Services;
|
||
using Moq;
|
||
using Xunit;
|
||
|
||
namespace MiAssessment.Tests.Admin;
|
||
|
||
/// <summary>
|
||
/// 业务介绍页服务属性测试
|
||
/// 验证业务介绍页服务的正确性属性
|
||
/// </summary>
|
||
public class BusinessPageServicePropertyTests
|
||
{
|
||
private readonly Mock<ILogger<BusinessPageService>> _mockLogger = new();
|
||
|
||
#region Property 10: 业务介绍页验证规则
|
||
|
||
/// <summary>
|
||
/// Feature: admin-missing-modules, Property 10: 业务介绍页验证规则
|
||
/// *For any* CreateBusinessPageRequest or UpdateBusinessPageRequest, if Title is empty or ImageUrl is empty,
|
||
/// the service must reject the request. Additionally, if HasActionButton is true and ActionButtonText
|
||
/// or ActionButtonLink is empty, the service must reject the request.
|
||
/// **Validates: Requirements 5.1, 5.2, 7.1, 7.2**
|
||
/// </summary>
|
||
[Property(MaxTest = 100)]
|
||
public bool BusinessPageValidationRejectsInvalid_EmptyTitleRejected(PositiveInt seed)
|
||
{
|
||
// Arrange: 创建数据库上下文
|
||
using var dbContext = CreateDbContext();
|
||
var service = new BusinessPageService(dbContext, _mockLogger.Object);
|
||
|
||
// 创建一个 Title 为空的请求
|
||
var request = new CreateBusinessPageRequest
|
||
{
|
||
Title = string.Empty, // 空标题
|
||
ImageUrl = $"https://example.com/image_{seed.Get}.jpg",
|
||
HasActionButton = false,
|
||
Sort = 0,
|
||
Status = 1
|
||
};
|
||
|
||
// Act & Assert: 服务应该拒绝空标题的请求
|
||
try
|
||
{
|
||
service.CreatePageAsync(request).GetAwaiter().GetResult();
|
||
return false; // 如果没有抛出异常,测试失败
|
||
}
|
||
catch (BusinessException ex)
|
||
{
|
||
return ex.Code == ErrorCodes.ParamError;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Feature: admin-missing-modules, Property 10: 业务介绍页验证规则
|
||
/// 验证空 ImageUrl 被拒绝
|
||
/// **Validates: Requirements 5.1, 5.2, 7.1, 7.2**
|
||
/// </summary>
|
||
[Property(MaxTest = 100)]
|
||
public bool BusinessPageValidationRejectsInvalid_EmptyImageUrlRejected(PositiveInt seed)
|
||
{
|
||
// Arrange: 创建数据库上下文
|
||
using var dbContext = CreateDbContext();
|
||
var service = new BusinessPageService(dbContext, _mockLogger.Object);
|
||
|
||
// 创建一个 ImageUrl 为空的请求
|
||
var request = new CreateBusinessPageRequest
|
||
{
|
||
Title = $"测试标题_{seed.Get}",
|
||
ImageUrl = string.Empty, // 空图片URL
|
||
HasActionButton = false,
|
||
Sort = 0,
|
||
Status = 1
|
||
};
|
||
|
||
// Act & Assert: 服务应该拒绝空图片URL的请求
|
||
try
|
||
{
|
||
service.CreatePageAsync(request).GetAwaiter().GetResult();
|
||
return false; // 如果没有抛出异常,测试失败
|
||
}
|
||
catch (BusinessException ex)
|
||
{
|
||
return ex.Code == ErrorCodes.ParamError;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Feature: admin-missing-modules, Property 10: 业务介绍页验证规则
|
||
/// 验证当 HasActionButton 为 true 时,空 ActionButtonText 被拒绝
|
||
/// **Validates: Requirements 5.1, 5.2, 7.1, 7.2**
|
||
/// </summary>
|
||
[Property(MaxTest = 100)]
|
||
public bool BusinessPageValidationRejectsInvalid_EmptyActionButtonTextRejected(PositiveInt seed)
|
||
{
|
||
// Arrange: 创建数据库上下文
|
||
using var dbContext = CreateDbContext();
|
||
var service = new BusinessPageService(dbContext, _mockLogger.Object);
|
||
|
||
// 创建一个 HasActionButton 为 true 但 ActionButtonText 为空的请求
|
||
var request = new CreateBusinessPageRequest
|
||
{
|
||
Title = $"测试标题_{seed.Get}",
|
||
ImageUrl = $"https://example.com/image_{seed.Get}.jpg",
|
||
HasActionButton = true, // 启用操作按钮
|
||
ActionButtonText = string.Empty, // 空按钮文字
|
||
ActionButtonLink = "https://example.com/link",
|
||
Sort = 0,
|
||
Status = 1
|
||
};
|
||
|
||
// Act & Assert: 服务应该拒绝空按钮文字的请求
|
||
try
|
||
{
|
||
service.CreatePageAsync(request).GetAwaiter().GetResult();
|
||
return false; // 如果没有抛出异常,测试失败
|
||
}
|
||
catch (BusinessException ex)
|
||
{
|
||
return ex.Code == ErrorCodes.ParamError;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Feature: admin-missing-modules, Property 10: 业务介绍页验证规则
|
||
/// 验证当 HasActionButton 为 true 时,空 ActionButtonLink 被拒绝
|
||
/// **Validates: Requirements 5.1, 5.2, 7.1, 7.2**
|
||
/// </summary>
|
||
[Property(MaxTest = 100)]
|
||
public bool BusinessPageValidationRejectsInvalid_EmptyActionButtonLinkRejected(PositiveInt seed)
|
||
{
|
||
// Arrange: 创建数据库上下文
|
||
using var dbContext = CreateDbContext();
|
||
var service = new BusinessPageService(dbContext, _mockLogger.Object);
|
||
|
||
// 创建一个 HasActionButton 为 true 但 ActionButtonLink 为空的请求
|
||
var request = new CreateBusinessPageRequest
|
||
{
|
||
Title = $"测试标题_{seed.Get}",
|
||
ImageUrl = $"https://example.com/image_{seed.Get}.jpg",
|
||
HasActionButton = true, // 启用操作按钮
|
||
ActionButtonText = "点击查看",
|
||
ActionButtonLink = string.Empty, // 空按钮链接
|
||
Sort = 0,
|
||
Status = 1
|
||
};
|
||
|
||
// Act & Assert: 服务应该拒绝空按钮链接的请求
|
||
try
|
||
{
|
||
service.CreatePageAsync(request).GetAwaiter().GetResult();
|
||
return false; // 如果没有抛出异常,测试失败
|
||
}
|
||
catch (BusinessException ex)
|
||
{
|
||
return ex.Code == ErrorCodes.ParamError;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Feature: admin-missing-modules, Property 10: 业务介绍页验证规则
|
||
/// 验证更新请求中空 Title 被拒绝
|
||
/// **Validates: Requirements 5.1, 5.2, 7.1, 7.2**
|
||
/// </summary>
|
||
[Property(MaxTest = 100)]
|
||
public bool BusinessPageValidationRejectsInvalid_UpdateEmptyTitleRejected(PositiveInt seed)
|
||
{
|
||
// Arrange: 创建数据库上下文并添加一个业务介绍页
|
||
using var dbContext = CreateDbContext();
|
||
var existingPage = CreateTestBusinessPage(dbContext, seed.Get);
|
||
var service = new BusinessPageService(dbContext, _mockLogger.Object);
|
||
|
||
// 创建一个 Title 为空的更新请求
|
||
var request = new UpdateBusinessPageRequest
|
||
{
|
||
Id = existingPage.Id,
|
||
Title = string.Empty, // 空标题
|
||
ImageUrl = existingPage.ImageUrl,
|
||
HasActionButton = false,
|
||
Sort = 0,
|
||
Status = 1
|
||
};
|
||
|
||
// Act & Assert: 服务应该拒绝空标题的更新请求
|
||
try
|
||
{
|
||
service.UpdatePageAsync(request).GetAwaiter().GetResult();
|
||
return false; // 如果没有抛出异常,测试失败
|
||
}
|
||
catch (BusinessException ex)
|
||
{
|
||
return ex.Code == ErrorCodes.ParamError;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Feature: admin-missing-modules, Property 10: 业务介绍页验证规则
|
||
/// 验证更新请求中当 HasActionButton 为 true 时,空 ActionButtonText 被拒绝
|
||
/// **Validates: Requirements 5.1, 5.2, 7.1, 7.2**
|
||
/// </summary>
|
||
[Property(MaxTest = 100)]
|
||
public bool BusinessPageValidationRejectsInvalid_UpdateEmptyActionButtonTextRejected(PositiveInt seed)
|
||
{
|
||
// Arrange: 创建数据库上下文并添加一个业务介绍页
|
||
using var dbContext = CreateDbContext();
|
||
var existingPage = CreateTestBusinessPage(dbContext, seed.Get);
|
||
var service = new BusinessPageService(dbContext, _mockLogger.Object);
|
||
|
||
// 创建一个 HasActionButton 为 true 但 ActionButtonText 为空的更新请求
|
||
var request = new UpdateBusinessPageRequest
|
||
{
|
||
Id = existingPage.Id,
|
||
Title = existingPage.Title,
|
||
ImageUrl = existingPage.ImageUrl,
|
||
HasActionButton = true, // 启用操作按钮
|
||
ActionButtonText = string.Empty, // 空按钮文字
|
||
ActionButtonLink = "https://example.com/link",
|
||
Sort = 0,
|
||
Status = 1
|
||
};
|
||
|
||
// Act & Assert: 服务应该拒绝空按钮文字的更新请求
|
||
try
|
||
{
|
||
service.UpdatePageAsync(request).GetAwaiter().GetResult();
|
||
return false; // 如果没有抛出异常,测试失败
|
||
}
|
||
catch (BusinessException ex)
|
||
{
|
||
return ex.Code == ErrorCodes.ParamError;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Feature: admin-missing-modules, Property 10: 业务介绍页验证规则
|
||
/// 验证有效请求被接受(当 HasActionButton 为 false 时,ActionButtonText 和 ActionButtonLink 可以为空)
|
||
/// **Validates: Requirements 5.1, 5.2, 7.1, 7.2**
|
||
/// </summary>
|
||
[Property(MaxTest = 100)]
|
||
public bool BusinessPageValidationRejectsInvalid_ValidRequestWithoutActionButtonAccepted(PositiveInt seed)
|
||
{
|
||
// Arrange: 创建数据库上下文
|
||
using var dbContext = CreateDbContext();
|
||
var service = new BusinessPageService(dbContext, _mockLogger.Object);
|
||
|
||
// 创建一个有效的请求(HasActionButton 为 false)
|
||
var request = new CreateBusinessPageRequest
|
||
{
|
||
Title = $"测试标题_{seed.Get}",
|
||
ImageUrl = $"https://example.com/image_{seed.Get}.jpg",
|
||
HasActionButton = false, // 不启用操作按钮
|
||
ActionButtonText = null, // 可以为空
|
||
ActionButtonLink = null, // 可以为空
|
||
Sort = seed.Get % 100,
|
||
Status = 1
|
||
};
|
||
|
||
// Act: 创建业务介绍页
|
||
try
|
||
{
|
||
var pageId = service.CreatePageAsync(request).GetAwaiter().GetResult();
|
||
return pageId > 0; // 成功创建
|
||
}
|
||
catch
|
||
{
|
||
return false; // 不应该抛出异常
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Feature: admin-missing-modules, Property 10: 业务介绍页验证规则
|
||
/// 验证有效请求被接受(当 HasActionButton 为 true 且 ActionButtonText 和 ActionButtonLink 都有值时)
|
||
/// **Validates: Requirements 5.1, 5.2, 7.1, 7.2**
|
||
/// </summary>
|
||
[Property(MaxTest = 100)]
|
||
public bool BusinessPageValidationRejectsInvalid_ValidRequestWithActionButtonAccepted(PositiveInt seed)
|
||
{
|
||
// Arrange: 创建数据库上下文
|
||
using var dbContext = CreateDbContext();
|
||
var service = new BusinessPageService(dbContext, _mockLogger.Object);
|
||
|
||
// 创建一个有效的请求(HasActionButton 为 true,且按钮文字和链接都有值)
|
||
var request = new CreateBusinessPageRequest
|
||
{
|
||
Title = $"测试标题_{seed.Get}",
|
||
ImageUrl = $"https://example.com/image_{seed.Get}.jpg",
|
||
HasActionButton = true, // 启用操作按钮
|
||
ActionButtonText = "点击查看",
|
||
ActionButtonLink = "https://example.com/link",
|
||
Sort = seed.Get % 100,
|
||
Status = 1
|
||
};
|
||
|
||
// Act: 创建业务介绍页
|
||
try
|
||
{
|
||
var pageId = service.CreatePageAsync(request).GetAwaiter().GetResult();
|
||
return pageId > 0; // 成功创建
|
||
}
|
||
catch
|
||
{
|
||
return false; // 不应该抛出异常
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Property 11: 业务介绍页创建默认值
|
||
|
||
/// <summary>
|
||
/// Feature: admin-missing-modules, Property 11: 业务介绍页创建默认值
|
||
/// *For any* valid CreateBusinessPageRequest, the created entity must have CreateTime and UpdateTime
|
||
/// set to approximately the current time, Status set to the request value (default 1),
|
||
/// and IsDeleted set to false.
|
||
/// **Validates: Requirements 5.3, 5.4**
|
||
/// </summary>
|
||
[Property(MaxTest = 100)]
|
||
public bool BusinessPageCreationDefaults_CreateTimeSetCorrectly(PositiveInt seed)
|
||
{
|
||
// Arrange: 创建数据库上下文
|
||
using var dbContext = CreateDbContext();
|
||
var service = new BusinessPageService(dbContext, _mockLogger.Object);
|
||
|
||
var beforeCreate = DateTime.Now.AddSeconds(-1);
|
||
|
||
// 创建一个有效的请求
|
||
var request = new CreateBusinessPageRequest
|
||
{
|
||
Title = $"测试标题_{seed.Get}",
|
||
ImageUrl = $"https://example.com/image_{seed.Get}.jpg",
|
||
HasActionButton = false,
|
||
Sort = seed.Get % 100,
|
||
Status = 1
|
||
};
|
||
|
||
// Act: 创建业务介绍页
|
||
var pageId = service.CreatePageAsync(request).GetAwaiter().GetResult();
|
||
var afterCreate = DateTime.Now.AddSeconds(1);
|
||
|
||
// 从数据库获取创建的实体
|
||
var entity = dbContext.BusinessPages.Find(pageId);
|
||
|
||
// Assert: CreateTime 应该在创建前后的时间范围内
|
||
return entity != null
|
||
&& entity.CreateTime >= beforeCreate
|
||
&& entity.CreateTime <= afterCreate;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Feature: admin-missing-modules, Property 11: 业务介绍页创建默认值
|
||
/// 验证 UpdateTime 设置正确
|
||
/// **Validates: Requirements 5.3, 5.4**
|
||
/// </summary>
|
||
[Property(MaxTest = 100)]
|
||
public bool BusinessPageCreationDefaults_UpdateTimeSetCorrectly(PositiveInt seed)
|
||
{
|
||
// Arrange: 创建数据库上下文
|
||
using var dbContext = CreateDbContext();
|
||
var service = new BusinessPageService(dbContext, _mockLogger.Object);
|
||
|
||
var beforeCreate = DateTime.Now.AddSeconds(-1);
|
||
|
||
// 创建一个有效的请求
|
||
var request = new CreateBusinessPageRequest
|
||
{
|
||
Title = $"测试标题_{seed.Get}",
|
||
ImageUrl = $"https://example.com/image_{seed.Get}.jpg",
|
||
HasActionButton = false,
|
||
Sort = seed.Get % 100,
|
||
Status = 1
|
||
};
|
||
|
||
// Act: 创建业务介绍页
|
||
var pageId = service.CreatePageAsync(request).GetAwaiter().GetResult();
|
||
var afterCreate = DateTime.Now.AddSeconds(1);
|
||
|
||
// 从数据库获取创建的实体
|
||
var entity = dbContext.BusinessPages.Find(pageId);
|
||
|
||
// Assert: UpdateTime 应该在创建前后的时间范围内
|
||
return entity != null
|
||
&& entity.UpdateTime >= beforeCreate
|
||
&& entity.UpdateTime <= afterCreate;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Feature: admin-missing-modules, Property 11: 业务介绍页创建默认值
|
||
/// 验证 Status 设置为请求值
|
||
/// **Validates: Requirements 5.3, 5.4**
|
||
/// </summary>
|
||
[Property(MaxTest = 100)]
|
||
public bool BusinessPageCreationDefaults_StatusSetToRequestValue(PositiveInt seed)
|
||
{
|
||
// Arrange: 创建数据库上下文
|
||
using var dbContext = CreateDbContext();
|
||
var service = new BusinessPageService(dbContext, _mockLogger.Object);
|
||
|
||
// 随机选择状态值 0 或 1
|
||
var requestStatus = seed.Get % 2;
|
||
|
||
// 创建一个有效的请求
|
||
var request = new CreateBusinessPageRequest
|
||
{
|
||
Title = $"测试标题_{seed.Get}",
|
||
ImageUrl = $"https://example.com/image_{seed.Get}.jpg",
|
||
HasActionButton = false,
|
||
Sort = seed.Get % 100,
|
||
Status = requestStatus
|
||
};
|
||
|
||
// Act: 创建业务介绍页
|
||
var pageId = service.CreatePageAsync(request).GetAwaiter().GetResult();
|
||
|
||
// 从数据库获取创建的实体
|
||
var entity = dbContext.BusinessPages.Find(pageId);
|
||
|
||
// Assert: Status 应该等于请求中的值
|
||
return entity != null && entity.Status == requestStatus;
|
||
}
|
||
///
|
||
|
||
/// <summary>
|
||
/// Feature: admin-missing-modules, Property 11: 业务介绍页创建默认值
|
||
/// 验证 IsDeleted 设置为 false
|
||
/// **Validates: Requirements 5.3, 5.4**
|
||
/// </summary>
|
||
[Property(MaxTest = 100)]
|
||
public bool BusinessPageCreationDefaults_IsDeletedSetToFalse(PositiveInt seed)
|
||
{
|
||
// Arrange: 创建数据库上下文
|
||
using var dbContext = CreateDbContext();
|
||
var service = new BusinessPageService(dbContext, _mockLogger.Object);
|
||
|
||
// 创建一个有效的请求
|
||
var request = new CreateBusinessPageRequest
|
||
{
|
||
Title = $"测试标题_{seed.Get}",
|
||
ImageUrl = $"https://example.com/image_{seed.Get}.jpg",
|
||
HasActionButton = false,
|
||
Sort = seed.Get % 100,
|
||
Status = 1
|
||
};
|
||
|
||
// Act: 创建业务介绍页
|
||
var pageId = service.CreatePageAsync(request).GetAwaiter().GetResult();
|
||
|
||
// 从数据库获取创建的实体
|
||
var entity = dbContext.BusinessPages.Find(pageId);
|
||
|
||
// Assert: IsDeleted 应该为 false
|
||
return entity != null && entity.IsDeleted == false;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Feature: admin-missing-modules, Property 11: 业务介绍页创建默认值
|
||
/// 验证默认 Status 为 1(启用)
|
||
/// **Validates: Requirements 5.3, 5.4**
|
||
/// </summary>
|
||
[Property(MaxTest = 100)]
|
||
public bool BusinessPageCreationDefaults_DefaultStatusIsEnabled(PositiveInt seed)
|
||
{
|
||
// Arrange: 创建数据库上下文
|
||
using var dbContext = CreateDbContext();
|
||
var service = new BusinessPageService(dbContext, _mockLogger.Object);
|
||
|
||
// 创建一个使用默认 Status 的请求
|
||
var request = new CreateBusinessPageRequest
|
||
{
|
||
Title = $"测试标题_{seed.Get}",
|
||
ImageUrl = $"https://example.com/image_{seed.Get}.jpg",
|
||
HasActionButton = false,
|
||
Sort = seed.Get % 100
|
||
// Status 使用默认值 1
|
||
};
|
||
|
||
// Act: 创建业务介绍页
|
||
var pageId = service.CreatePageAsync(request).GetAwaiter().GetResult();
|
||
|
||
// 从数据库获取创建的实体
|
||
var entity = dbContext.BusinessPages.Find(pageId);
|
||
|
||
// Assert: 默认 Status 应该为 1(启用)
|
||
return entity != null && entity.Status == 1;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Feature: admin-missing-modules, Property 11: 业务介绍页创建默认值
|
||
/// 验证 CreateTime 和 UpdateTime 相等(新创建时)
|
||
/// **Validates: Requirements 5.3, 5.4**
|
||
/// </summary>
|
||
[Property(MaxTest = 100)]
|
||
public bool BusinessPageCreationDefaults_CreateTimeEqualsUpdateTime(PositiveInt seed)
|
||
{
|
||
// Arrange: 创建数据库上下文
|
||
using var dbContext = CreateDbContext();
|
||
var service = new BusinessPageService(dbContext, _mockLogger.Object);
|
||
|
||
// 创建一个有效的请求
|
||
var request = new CreateBusinessPageRequest
|
||
{
|
||
Title = $"测试标题_{seed.Get}",
|
||
ImageUrl = $"https://example.com/image_{seed.Get}.jpg",
|
||
HasActionButton = false,
|
||
Sort = seed.Get % 100,
|
||
Status = 1
|
||
};
|
||
|
||
// Act: 创建业务介绍页
|
||
var pageId = service.CreatePageAsync(request).GetAwaiter().GetResult();
|
||
|
||
// 从数据库获取创建的实体
|
||
var entity = dbContext.BusinessPages.Find(pageId);
|
||
|
||
// Assert: CreateTime 和 UpdateTime 应该相等
|
||
return entity != null && entity.CreateTime == entity.UpdateTime;
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region Property 15: 业务介绍页 CRUD 往返一致性
|
||
|
||
/// <summary>
|
||
/// Feature: admin-missing-modules, Property 15: 业务介绍页 CRUD 往返一致性
|
||
/// *For any* valid CreateBusinessPageRequest, creating a page and then reading it back via GetPageByIdAsync
|
||
/// must return an entity with matching Title, ImageUrl, HasActionButton, ActionButtonText,
|
||
/// ActionButtonLink, and Sort values.
|
||
/// **Validates: Requirements 5.1, 6.3, 7.1**
|
||
/// </summary>
|
||
[Property(MaxTest = 100)]
|
||
public bool BusinessPageCrudRoundTrip_TitleMatches(PositiveInt seed)
|
||
{
|
||
// Arrange: 创建数据库上下文
|
||
using var dbContext = CreateDbContext();
|
||
var service = new BusinessPageService(dbContext, _mockLogger.Object);
|
||
|
||
var expectedTitle = $"测试标题_{seed.Get}_{Guid.NewGuid():N}";
|
||
|
||
// 创建一个有效的请求
|
||
var request = new CreateBusinessPageRequest
|
||
{
|
||
Title = expectedTitle,
|
||
ImageUrl = $"https://example.com/image_{seed.Get}.jpg",
|
||
HasActionButton = false,
|
||
Sort = seed.Get % 100,
|
||
Status = 1
|
||
};
|
||
|
||
// Act: 创建业务介绍页并读取回来
|
||
var pageId = service.CreatePageAsync(request).GetAwaiter().GetResult();
|
||
var readBack = service.GetPageByIdAsync(pageId).GetAwaiter().GetResult();
|
||
|
||
// Assert: Title 应该匹配
|
||
return readBack != null && readBack.Title == expectedTitle;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Feature: admin-missing-modules, Property 15: 业务介绍页 CRUD 往返一致性
|
||
/// 验证 ImageUrl 匹配
|
||
/// **Validates: Requirements 5.1, 6.3, 7.1**
|
||
/// </summary>
|
||
[Property(MaxTest = 100)]
|
||
public bool BusinessPageCrudRoundTrip_ImageUrlMatches(PositiveInt seed)
|
||
{
|
||
// Arrange: 创建数据库上下文
|
||
using var dbContext = CreateDbContext();
|
||
var service = new BusinessPageService(dbContext, _mockLogger.Object);
|
||
|
||
var expectedImageUrl = $"https://example.com/image_{seed.Get}_{Guid.NewGuid():N}.jpg";
|
||
|
||
// 创建一个有效的请求
|
||
var request = new CreateBusinessPageRequest
|
||
{
|
||
Title = $"测试标题_{seed.Get}",
|
||
ImageUrl = expectedImageUrl,
|
||
HasActionButton = false,
|
||
Sort = seed.Get % 100,
|
||
Status = 1
|
||
};
|
||
|
||
// Act: 创建业务介绍页并读取回来
|
||
var pageId = service.CreatePageAsync(request).GetAwaiter().GetResult();
|
||
var readBack = service.GetPageByIdAsync(pageId).GetAwaiter().GetResult();
|
||
|
||
// Assert: ImageUrl 应该匹配
|
||
return readBack != null && readBack.ImageUrl == expectedImageUrl;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Feature: admin-missing-modules, Property 15: 业务介绍页 CRUD 往返一致性
|
||
/// 验证 HasActionButton 匹配
|
||
/// **Validates: Requirements 5.1, 6.3, 7.1**
|
||
/// </summary>
|
||
[Property(MaxTest = 100)]
|
||
public bool BusinessPageCrudRoundTrip_HasActionButtonMatches(PositiveInt seed)
|
||
{
|
||
// Arrange: 创建数据库上下文
|
||
using var dbContext = CreateDbContext();
|
||
var service = new BusinessPageService(dbContext, _mockLogger.Object);
|
||
|
||
var expectedHasActionButton = seed.Get % 2 == 0;
|
||
|
||
// 创建一个有效的请求
|
||
var request = new CreateBusinessPageRequest
|
||
{
|
||
Title = $"测试标题_{seed.Get}",
|
||
ImageUrl = $"https://example.com/image_{seed.Get}.jpg",
|
||
HasActionButton = expectedHasActionButton,
|
||
ActionButtonText = expectedHasActionButton ? "点击查看" : null,
|
||
ActionButtonLink = expectedHasActionButton ? "https://example.com/link" : null,
|
||
Sort = seed.Get % 100,
|
||
Status = 1
|
||
};
|
||
|
||
// Act: 创建业务介绍页并读取回来
|
||
var pageId = service.CreatePageAsync(request).GetAwaiter().GetResult();
|
||
var readBack = service.GetPageByIdAsync(pageId).GetAwaiter().GetResult();
|
||
|
||
// Assert: HasActionButton 应该匹配
|
||
return readBack != null && readBack.HasActionButton == expectedHasActionButton;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Feature: admin-missing-modules, Property 15: 业务介绍页 CRUD 往返一致性
|
||
/// 验证 ActionButtonText 匹配
|
||
/// **Validates: Requirements 5.1, 6.3, 7.1**
|
||
/// </summary>
|
||
[Property(MaxTest = 100)]
|
||
public bool BusinessPageCrudRoundTrip_ActionButtonTextMatches(PositiveInt seed)
|
||
{
|
||
// Arrange: 创建数据库上下文
|
||
using var dbContext = CreateDbContext();
|
||
var service = new BusinessPageService(dbContext, _mockLogger.Object);
|
||
|
||
var expectedActionButtonText = $"按钮文字_{seed.Get}";
|
||
|
||
// 创建一个有效的请求(启用操作按钮)
|
||
var request = new CreateBusinessPageRequest
|
||
{
|
||
Title = $"测试标题_{seed.Get}",
|
||
ImageUrl = $"https://example.com/image_{seed.Get}.jpg",
|
||
HasActionButton = true,
|
||
ActionButtonText = expectedActionButtonText,
|
||
ActionButtonLink = "https://example.com/link",
|
||
Sort = seed.Get % 100,
|
||
Status = 1
|
||
};
|
||
|
||
// Act: 创建业务介绍页并读取回来
|
||
var pageId = service.CreatePageAsync(request).GetAwaiter().GetResult();
|
||
var readBack = service.GetPageByIdAsync(pageId).GetAwaiter().GetResult();
|
||
|
||
// Assert: ActionButtonText 应该匹配
|
||
return readBack != null && readBack.ActionButtonText == expectedActionButtonText;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Feature: admin-missing-modules, Property 15: 业务介绍页 CRUD 往返一致性
|
||
/// 验证 ActionButtonLink 匹配
|
||
/// **Validates: Requirements 5.1, 6.3, 7.1**
|
||
/// </summary>
|
||
[Property(MaxTest = 100)]
|
||
public bool BusinessPageCrudRoundTrip_ActionButtonLinkMatches(PositiveInt seed)
|
||
{
|
||
// Arrange: 创建数据库上下文
|
||
using var dbContext = CreateDbContext();
|
||
var service = new BusinessPageService(dbContext, _mockLogger.Object);
|
||
|
||
var expectedActionButtonLink = $"https://example.com/link_{seed.Get}";
|
||
|
||
// 创建一个有效的请求(启用操作按钮)
|
||
var request = new CreateBusinessPageRequest
|
||
{
|
||
Title = $"测试标题_{seed.Get}",
|
||
ImageUrl = $"https://example.com/image_{seed.Get}.jpg",
|
||
HasActionButton = true,
|
||
ActionButtonText = "点击查看",
|
||
ActionButtonLink = expectedActionButtonLink,
|
||
Sort = seed.Get % 100,
|
||
Status = 1
|
||
};
|
||
|
||
// Act: 创建业务介绍页并读取回来
|
||
var pageId = service.CreatePageAsync(request).GetAwaiter().GetResult();
|
||
var readBack = service.GetPageByIdAsync(pageId).GetAwaiter().GetResult();
|
||
|
||
// Assert: ActionButtonLink 应该匹配
|
||
return readBack != null && readBack.ActionButtonLink == expectedActionButtonLink;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Feature: admin-missing-modules, Property 15: 业务介绍页 CRUD 往返一致性
|
||
/// 验证 Sort 匹配
|
||
/// **Validates: Requirements 5.1, 6.3, 7.1**
|
||
/// </summary>
|
||
[Property(MaxTest = 100)]
|
||
public bool BusinessPageCrudRoundTrip_SortMatches(PositiveInt seed)
|
||
{
|
||
// Arrange: 创建数据库上下文
|
||
using var dbContext = CreateDbContext();
|
||
var service = new BusinessPageService(dbContext, _mockLogger.Object);
|
||
|
||
var expectedSort = seed.Get % 1000;
|
||
|
||
// 创建一个有效的请求
|
||
var request = new CreateBusinessPageRequest
|
||
{
|
||
Title = $"测试标题_{seed.Get}",
|
||
ImageUrl = $"https://example.com/image_{seed.Get}.jpg",
|
||
HasActionButton = false,
|
||
Sort = expectedSort,
|
||
Status = 1
|
||
};
|
||
|
||
// Act: 创建业务介绍页并读取回来
|
||
var pageId = service.CreatePageAsync(request).GetAwaiter().GetResult();
|
||
var readBack = service.GetPageByIdAsync(pageId).GetAwaiter().GetResult();
|
||
|
||
// Assert: Sort 应该匹配
|
||
return readBack != null && readBack.Sort == expectedSort;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Feature: admin-missing-modules, Property 15: 业务介绍页 CRUD 往返一致性
|
||
/// 验证所有字段同时匹配
|
||
/// **Validates: Requirements 5.1, 6.3, 7.1**
|
||
/// </summary>
|
||
[Property(MaxTest = 100)]
|
||
public bool BusinessPageCrudRoundTrip_AllFieldsMatch(PositiveInt seed)
|
||
{
|
||
// Arrange: 创建数据库上下文
|
||
using var dbContext = CreateDbContext();
|
||
var service = new BusinessPageService(dbContext, _mockLogger.Object);
|
||
|
||
var hasActionButton = seed.Get % 2 == 0;
|
||
var expectedTitle = $"测试标题_{seed.Get}_{Guid.NewGuid():N}";
|
||
var expectedImageUrl = $"https://example.com/image_{seed.Get}_{Guid.NewGuid():N}.jpg";
|
||
var expectedActionButtonText = hasActionButton ? $"按钮文字_{seed.Get}" : null;
|
||
var expectedActionButtonLink = hasActionButton ? $"https://example.com/link_{seed.Get}" : null;
|
||
var expectedSort = seed.Get % 1000;
|
||
|
||
// 创建一个有效的请求
|
||
var request = new CreateBusinessPageRequest
|
||
{
|
||
Title = expectedTitle,
|
||
ImageUrl = expectedImageUrl,
|
||
HasActionButton = hasActionButton,
|
||
ActionButtonText = expectedActionButtonText,
|
||
ActionButtonLink = expectedActionButtonLink,
|
||
Sort = expectedSort,
|
||
Status = 1
|
||
};
|
||
|
||
// Act: 创建业务介绍页并读取回来
|
||
var pageId = service.CreatePageAsync(request).GetAwaiter().GetResult();
|
||
var readBack = service.GetPageByIdAsync(pageId).GetAwaiter().GetResult();
|
||
|
||
// Assert: 所有字段都应该匹配
|
||
return readBack != null
|
||
&& readBack.Title == expectedTitle
|
||
&& readBack.ImageUrl == expectedImageUrl
|
||
&& readBack.HasActionButton == hasActionButton
|
||
&& readBack.ActionButtonText == expectedActionButtonText
|
||
&& readBack.ActionButtonLink == expectedActionButtonLink
|
||
&& readBack.Sort == expectedSort;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Feature: admin-missing-modules, Property 15: 业务介绍页 CRUD 往返一致性
|
||
/// 验证更新后读取回来的数据一致
|
||
/// **Validates: Requirements 5.1, 6.3, 7.1**
|
||
/// </summary>
|
||
[Property(MaxTest = 100)]
|
||
public bool BusinessPageCrudRoundTrip_UpdateAndReadBackMatches(PositiveInt seed)
|
||
{
|
||
// Arrange: 创建数据库上下文并创建初始页面
|
||
using var dbContext = CreateDbContext();
|
||
var service = new BusinessPageService(dbContext, _mockLogger.Object);
|
||
|
||
// 创建初始页面
|
||
var createRequest = new CreateBusinessPageRequest
|
||
{
|
||
Title = $"初始标题_{seed.Get}",
|
||
ImageUrl = $"https://example.com/initial_{seed.Get}.jpg",
|
||
HasActionButton = false,
|
||
Sort = 0,
|
||
Status = 1
|
||
};
|
||
var pageId = service.CreatePageAsync(createRequest).GetAwaiter().GetResult();
|
||
|
||
// 更新页面
|
||
var hasActionButton = seed.Get % 2 == 0;
|
||
var expectedTitle = $"更新标题_{seed.Get}_{Guid.NewGuid():N}";
|
||
var expectedImageUrl = $"https://example.com/updated_{seed.Get}_{Guid.NewGuid():N}.jpg";
|
||
var expectedActionButtonText = hasActionButton ? $"更新按钮_{seed.Get}" : null;
|
||
var expectedActionButtonLink = hasActionButton ? $"https://example.com/updated_link_{seed.Get}" : null;
|
||
var expectedSort = (seed.Get + 100) % 1000;
|
||
|
||
var updateRequest = new UpdateBusinessPageRequest
|
||
{
|
||
Id = pageId,
|
||
Title = expectedTitle,
|
||
ImageUrl = expectedImageUrl,
|
||
HasActionButton = hasActionButton,
|
||
ActionButtonText = expectedActionButtonText,
|
||
ActionButtonLink = expectedActionButtonLink,
|
||
Sort = expectedSort,
|
||
Status = 1
|
||
};
|
||
|
||
// Act: 更新并读取回来
|
||
service.UpdatePageAsync(updateRequest).GetAwaiter().GetResult();
|
||
var readBack = service.GetPageByIdAsync(pageId).GetAwaiter().GetResult();
|
||
|
||
// Assert: 更新后的所有字段都应该匹配
|
||
return readBack != null
|
||
&& readBack.Title == expectedTitle
|
||
&& readBack.ImageUrl == expectedImageUrl
|
||
&& readBack.HasActionButton == hasActionButton
|
||
&& readBack.ActionButtonText == expectedActionButtonText
|
||
&& readBack.ActionButtonLink == expectedActionButtonLink
|
||
&& readBack.Sort == expectedSort;
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 辅助方法
|
||
|
||
/// <summary>
|
||
/// 创建内存数据库上下文
|
||
/// </summary>
|
||
private AdminBusinessDbContext CreateDbContext()
|
||
{
|
||
var options = new DbContextOptionsBuilder<AdminBusinessDbContext>()
|
||
.UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString())
|
||
.Options;
|
||
|
||
return new AdminBusinessDbContext(options);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建测试业务介绍页
|
||
/// </summary>
|
||
private BusinessPage CreateTestBusinessPage(AdminBusinessDbContext dbContext, int seed)
|
||
{
|
||
var page = new BusinessPage
|
||
{
|
||
Title = $"测试标题_{seed}",
|
||
ImageUrl = $"https://example.com/image_{seed}.jpg",
|
||
HasActionButton = false,
|
||
ActionButtonText = null,
|
||
ActionButtonLink = null,
|
||
Sort = seed % 100,
|
||
Status = 1,
|
||
CreateTime = DateTime.Now,
|
||
UpdateTime = DateTime.Now,
|
||
IsDeleted = false
|
||
};
|
||
dbContext.BusinessPages.Add(page);
|
||
dbContext.SaveChanges();
|
||
return page;
|
||
}
|
||
|
||
#endregion
|
||
}
|