HaniBlindBox/server/HoneyBox/tests/HoneyBox.Tests/Services/RewardServiceTests.cs
2026-01-18 12:42:28 +08:00

482 lines
13 KiB
C#

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;
/// <summary>
/// RewardService 单元测试
/// </summary>
public class RewardServiceTests : IDisposable
{
private readonly HoneyBoxDbContext _dbContext;
private readonly Mock<ILogger<RewardService>> _mockLogger;
private readonly RewardService _rewardService;
public RewardServiceTests()
{
// 使用 InMemory 数据库
var options = new DbContextOptionsBuilder<HoneyBoxDbContext>()
.UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString())
.Options;
_dbContext = new HoneyBoxDbContext(options);
_mockLogger = new Mock<ILogger<RewardService>>();
_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<BusinessException>(
() => _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<BusinessException>(
() => _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<BusinessException>(
() => _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<BusinessException>(
() => _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<BusinessException>(
() => _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<RewardItem>
{
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<RewardItem>()
};
// Act & Assert
var ex = await Assert.ThrowsAsync<BusinessException>(
() => _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<RewardItem>()
};
// 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<Reward>
{
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
}