using HoneyBox.Admin.Business.Models; using HoneyBox.Admin.Business.Models.Reward; using HoneyBox.Admin.Business.Services; using HoneyBox.Model.Data; using HoneyBox.Model.Entities; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Moq; using Xunit; namespace HoneyBox.Tests.Services; /// /// RewardService 单元测试 /// public class RewardServiceTests : IDisposable { private readonly HoneyBoxDbContext _dbContext; private readonly Mock> _mockLogger; private readonly RewardService _rewardService; public RewardServiceTests() { // 使用 InMemory 数据库 var options = new DbContextOptionsBuilder() .UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString()) .Options; _dbContext = new HoneyBoxDbContext(options); _mockLogger = new Mock>(); _rewardService = new RewardService(_dbContext, _mockLogger.Object); } public void Dispose() { _dbContext.Dispose(); } #region GetRewardsAsync Tests [Fact] public async Task GetRewardsAsync_WithNoFilters_ReturnsAllRewards() { // Arrange await SeedTestRewards(); var request = new RewardListRequest { Page = 1, PageSize = 10 }; // Act var result = await _rewardService.GetRewardsAsync(request); // Assert Assert.NotNull(result); Assert.Equal(3, result.Total); Assert.Equal(3, result.List.Count); } [Fact] public async Task GetRewardsAsync_WithTypeFilter_ReturnsFilteredRewards() { // Arrange await SeedTestRewards(); var request = new RewardListRequest { Page = 1, PageSize = 10, RewardType = 1 }; // Act var result = await _rewardService.GetRewardsAsync(request); // Assert Assert.NotNull(result); Assert.Equal(1, result.Total); Assert.All(result.List, r => Assert.Equal(1, r.RewardType)); } [Fact] public async Task GetRewardsAsync_WithKeywordFilter_ReturnsFilteredRewards() { // Arrange await SeedTestRewards(); var request = new RewardListRequest { Page = 1, PageSize = 10, Keyword = "钻石" }; // Act var result = await _rewardService.GetRewardsAsync(request); // Assert Assert.NotNull(result); Assert.Equal(1, result.Total); Assert.Contains("钻石", result.List[0].Description); } [Fact] public async Task GetRewardsAsync_WithRewardIdFilter_ReturnsFilteredRewards() { // Arrange await SeedTestRewards(); var request = new RewardListRequest { Page = 1, PageSize = 10, RewardId = "reward_001" }; // Act var result = await _rewardService.GetRewardsAsync(request); // Assert Assert.NotNull(result); Assert.Equal(1, result.Total); Assert.Equal("reward_001", result.List[0].RewardId); } [Fact] public async Task GetRewardsAsync_WithPagination_ReturnsCorrectPage() { // Arrange await SeedTestRewards(); var request = new RewardListRequest { Page = 1, PageSize = 2 }; // Act var result = await _rewardService.GetRewardsAsync(request); // Assert Assert.NotNull(result); Assert.Equal(3, result.Total); Assert.Equal(2, result.List.Count); Assert.Equal(1, result.Page); Assert.Equal(2, result.PageSize); } #endregion #region GetRewardByIdAsync Tests [Fact] public async Task GetRewardByIdAsync_WithExistingId_ReturnsReward() { // Arrange await SeedTestRewards(); // Act var result = await _rewardService.GetRewardByIdAsync(1); // Assert Assert.NotNull(result); Assert.Equal(1, result.Id); } [Fact] public async Task GetRewardByIdAsync_WithNonExistingId_ReturnsNull() { // Arrange await SeedTestRewards(); // Act var result = await _rewardService.GetRewardByIdAsync(999); // Assert Assert.Null(result); } #endregion #region GetRewardsByRewardIdAsync Tests [Fact] public async Task GetRewardsByRewardIdAsync_WithExistingRewardId_ReturnsRewards() { // Arrange await SeedTestRewards(); // Act var result = await _rewardService.GetRewardsByRewardIdAsync("reward_001"); // Assert Assert.NotNull(result); Assert.Single(result); Assert.Equal("reward_001", result[0].RewardId); } [Fact] public async Task GetRewardsByRewardIdAsync_WithNonExistingRewardId_ReturnsEmptyList() { // Arrange await SeedTestRewards(); // Act var result = await _rewardService.GetRewardsByRewardIdAsync("non_existing"); // Assert Assert.NotNull(result); Assert.Empty(result); } [Fact] public async Task GetRewardsByRewardIdAsync_WithEmptyRewardId_ReturnsEmptyList() { // Arrange await SeedTestRewards(); // Act var result = await _rewardService.GetRewardsByRewardIdAsync(""); // Assert Assert.NotNull(result); Assert.Empty(result); } #endregion #region CreateRewardAsync Tests [Fact] public async Task CreateRewardAsync_WithValidDiamondReward_CreatesReward() { // Arrange var request = new RewardCreateRequest { RewardType = 1, RewardValue = 100, Description = "测试钻石奖励" }; // Act var id = await _rewardService.CreateRewardAsync(request); // Assert Assert.True(id > 0); var reward = await _dbContext.Rewards.FindAsync(id); Assert.NotNull(reward); Assert.Equal(1, reward.RewardType); Assert.Equal(100, reward.RewardValue); } [Fact] public async Task CreateRewardAsync_WithValidCouponReward_CreatesReward() { // Arrange var request = new RewardCreateRequest { RewardType = 4, RewardExtend = 1, RewardValue = 0, Description = "测试优惠券奖励" }; // Act var id = await _rewardService.CreateRewardAsync(request); // Assert Assert.True(id > 0); var reward = await _dbContext.Rewards.FindAsync(id); Assert.NotNull(reward); Assert.Equal(4, reward.RewardType); Assert.Equal(1, reward.RewardExtend); } [Fact] public async Task CreateRewardAsync_WithInvalidType_ThrowsException() { // Arrange var request = new RewardCreateRequest { RewardType = 5, RewardValue = 100 }; // Act & Assert var ex = await Assert.ThrowsAsync( () => _rewardService.CreateRewardAsync(request)); Assert.Equal(BusinessErrorCodes.ValidationFailed, ex.Code); } [Fact] public async Task CreateRewardAsync_WithCouponTypeButNoCouponId_ThrowsException() { // Arrange var request = new RewardCreateRequest { RewardType = 4, RewardValue = 0 }; // Act & Assert var ex = await Assert.ThrowsAsync( () => _rewardService.CreateRewardAsync(request)); Assert.Equal(BusinessErrorCodes.ValidationFailed, ex.Code); } [Fact] public async Task CreateRewardAsync_WithNonCouponTypeButZeroValue_ThrowsException() { // Arrange var request = new RewardCreateRequest { RewardType = 1, RewardValue = 0 }; // Act & Assert var ex = await Assert.ThrowsAsync( () => _rewardService.CreateRewardAsync(request)); Assert.Equal(BusinessErrorCodes.ValidationFailed, ex.Code); } #endregion #region UpdateRewardAsync Tests [Fact] public async Task UpdateRewardAsync_WithExistingReward_UpdatesReward() { // Arrange await SeedTestRewards(); var request = new RewardUpdateRequest { RewardType = 1, RewardValue = 200, Description = "更新后的描述" }; // Act var result = await _rewardService.UpdateRewardAsync(1, request); // Assert Assert.True(result); var reward = await _dbContext.Rewards.FindAsync(1); Assert.NotNull(reward); Assert.Equal(200, reward.RewardValue); Assert.Equal("更新后的描述", reward.Description); } [Fact] public async Task UpdateRewardAsync_WithNonExistingReward_ThrowsException() { // Arrange var request = new RewardUpdateRequest { RewardType = 1, RewardValue = 100 }; // Act & Assert var ex = await Assert.ThrowsAsync( () => _rewardService.UpdateRewardAsync(999, request)); Assert.Equal(BusinessErrorCodes.NotFound, ex.Code); } #endregion #region DeleteRewardAsync Tests [Fact] public async Task DeleteRewardAsync_WithExistingReward_DeletesReward() { // Arrange await SeedTestRewards(); // Act var result = await _rewardService.DeleteRewardAsync(1); // Assert Assert.True(result); var reward = await _dbContext.Rewards.FindAsync(1); Assert.Null(reward); } [Fact] public async Task DeleteRewardAsync_WithNonExistingReward_ThrowsException() { // Act & Assert var ex = await Assert.ThrowsAsync( () => _rewardService.DeleteRewardAsync(999)); Assert.Equal(BusinessErrorCodes.NotFound, ex.Code); } #endregion #region BatchUpdateRewardsAsync Tests [Fact] public async Task BatchUpdateRewardsAsync_WithValidRequest_UpdatesRewards() { // Arrange await SeedTestRewards(); var request = new RewardBatchRequest { RewardId = "reward_001", Rewards = new List { new() { RewardType = 1, RewardValue = 50, Description = "新钻石奖励" }, new() { RewardType = 2, RewardValue = 100, Description = "新UU币奖励" } } }; // Act var result = await _rewardService.BatchUpdateRewardsAsync(request); // Assert Assert.True(result); var rewards = await _dbContext.Rewards.Where(r => r.RewardId == "reward_001").ToListAsync(); Assert.Equal(2, rewards.Count); } [Fact] public async Task BatchUpdateRewardsAsync_WithEmptyRewardId_ThrowsException() { // Arrange var request = new RewardBatchRequest { RewardId = "", Rewards = new List() }; // Act & Assert var ex = await Assert.ThrowsAsync( () => _rewardService.BatchUpdateRewardsAsync(request)); Assert.Equal(BusinessErrorCodes.ValidationFailed, ex.Code); } [Fact] public async Task BatchUpdateRewardsAsync_WithEmptyRewardsList_DeletesExistingRewards() { // Arrange await SeedTestRewards(); var request = new RewardBatchRequest { RewardId = "reward_001", Rewards = new List() }; // Act var result = await _rewardService.BatchUpdateRewardsAsync(request); // Assert Assert.True(result); var rewards = await _dbContext.Rewards.Where(r => r.RewardId == "reward_001").ToListAsync(); Assert.Empty(rewards); } #endregion #region Helper Methods private async Task SeedTestRewards() { var rewards = new List { new() { Id = 1, RewardId = "reward_001", RewardType = 1, RewardValue = 100, Description = "钻石奖励", CreatedAt = DateTime.Now, UpdatedAt = DateTime.Now }, new() { Id = 2, RewardId = "reward_002", RewardType = 2, RewardValue = 50, Description = "UU币奖励", CreatedAt = DateTime.Now.AddMinutes(-1), UpdatedAt = DateTime.Now.AddMinutes(-1) }, new() { Id = 3, RewardId = "reward_003", RewardType = 3, RewardValue = 30, Description = "达达卷奖励", CreatedAt = DateTime.Now.AddMinutes(-2), UpdatedAt = DateTime.Now.AddMinutes(-2) } }; _dbContext.Rewards.AddRange(rewards); await _dbContext.SaveChangesAsync(); } #endregion }