using HoneyBox.Admin.Business.Models.Finance; 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; /// /// FinanceService 单元测试 /// public class FinanceServiceTests : IDisposable { private readonly HoneyBoxDbContext _dbContext; private readonly FinanceService _service; private readonly Mock> _mockLogger; public FinanceServiceTests() { var options = new DbContextOptionsBuilder() .UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString()) .Options; _dbContext = new HoneyBoxDbContext(options); _mockLogger = new Mock>(); _service = new FinanceService(_dbContext, _mockLogger.Object); } public void Dispose() { _dbContext.Dispose(); } #region 消费排行榜测试 [Fact] public async Task GetConsumptionRanking_ShouldReturnUsersOrderedByConsumption() { // Arrange SeedUsers(3); SeedOrders(); var request = new FinanceQueryRequest { Page = 1, PageSize = 10 }; // Act var result = await _service.GetConsumptionRankingAsync(request); // Assert Assert.NotNull(result); Assert.True(result.List.Count > 0); // 验证按消费金额降序排序 for (int i = 0; i < result.List.Count - 1; i++) { Assert.True(result.List[i].TotalConsumption >= result.List[i + 1].TotalConsumption); } } [Fact] public async Task GetConsumptionRanking_ShouldIncludeUserInfo() { // Arrange SeedUsers(1); SeedOrders(); var request = new FinanceQueryRequest { Page = 1, PageSize = 10 }; // Act var result = await _service.GetConsumptionRankingAsync(request); // Assert Assert.NotNull(result); if (result.List.Count > 0) { var first = result.List[0]; Assert.NotNull(first.Uid); Assert.NotNull(first.Nickname); } } #endregion #region 余额明细测试 [Fact] public async Task GetBalanceDetails_ShouldReturnPaginatedResults() { // Arrange SeedUsers(1); SeedProfitMoney(15); var request = new FinanceQueryRequest { Page = 1, PageSize = 10 }; // Act var result = await _service.GetBalanceDetailsAsync(request); // Assert Assert.NotNull(result); Assert.Equal(15, result.Total); Assert.Equal(10, result.List.Count); } [Fact] public async Task GetBalanceDetails_ShouldFilterByUserId() { // Arrange SeedUsers(3); SeedProfitMoneyForMultipleUsers(); var request = new FinanceQueryRequest { UserId = 1, Page = 1, PageSize = 20 }; // Act var result = await _service.GetBalanceDetailsAsync(request); // Assert Assert.NotNull(result); Assert.All(result.List, item => Assert.Equal(1, item.UserId)); } [Fact] public async Task GetBalanceDetails_ShouldFilterByDateRange() { // Arrange SeedUsers(1); SeedProfitMoneyWithDates(); var request = new FinanceQueryRequest { StartDate = DateTime.Today.AddDays(-3), EndDate = DateTime.Today, Page = 1, PageSize = 20 }; // Act var result = await _service.GetBalanceDetailsAsync(request); // Assert Assert.NotNull(result); Assert.All(result.List, item => { Assert.True(item.CreatedAt >= request.StartDate.Value.Date); Assert.True(item.CreatedAt < request.EndDate.Value.Date.AddDays(1)); }); } #endregion #region 积分明细测试 [Fact] public async Task GetIntegralDetails_ShouldReturnPaginatedResults() { // Arrange SeedUsers(1); SeedProfitIntegral(10); var request = new FinanceQueryRequest { Page = 1, PageSize = 5 }; // Act var result = await _service.GetIntegralDetailsAsync(request); // Assert Assert.NotNull(result); Assert.Equal(10, result.Total); Assert.Equal(5, result.List.Count); } [Fact] public async Task GetIntegralDetails_ShouldFilterByUserId() { // Arrange SeedUsers(2); SeedProfitIntegralForMultipleUsers(); var request = new FinanceQueryRequest { UserId = 2, Page = 1, PageSize = 20 }; // Act var result = await _service.GetIntegralDetailsAsync(request); // Assert Assert.NotNull(result); Assert.All(result.List, item => Assert.Equal(2, item.UserId)); } #endregion #region 钻石明细测试 [Fact] public async Task GetScoreDetails_ShouldReturnPaginatedResults() { // Arrange SeedUsers(1); SeedProfitScore(8); var request = new FinanceQueryRequest { Page = 1, PageSize = 5 }; // Act var result = await _service.GetScoreDetailsAsync(request); // Assert Assert.NotNull(result); Assert.Equal(8, result.Total); Assert.Equal(5, result.List.Count); } #endregion #region 充值记录测试 [Fact] public async Task GetRechargeRecords_ShouldReturnPaginatedResults() { // Arrange SeedUsers(1); SeedProfitPay(12); var request = new FinanceQueryRequest { Page = 1, PageSize = 10 }; // Act var result = await _service.GetRechargeRecordsAsync(request); // Assert Assert.NotNull(result); Assert.Equal(12, result.Total); Assert.Equal(10, result.List.Count); } [Fact] public async Task GetRechargeRecords_ShouldIncludePayTypeName() { // Arrange SeedUsers(1); SeedProfitPay(1); var request = new FinanceQueryRequest { Page = 1, PageSize = 10 }; // Act var result = await _service.GetRechargeRecordsAsync(request); // Assert Assert.NotNull(result); Assert.Single(result.List); Assert.NotEmpty(result.List[0].PayTypeName); } #endregion #region Helper Methods private void SeedUsers(int count) { for (int i = 1; i <= count; i++) { _dbContext.Users.Add(new User { Id = i, Uid = $"U{i:D3}", Nickname = $"测试用户{i}", Mobile = $"1380013800{i}", OpenId = $"openid{i}", HeadImg = $"http://test.com/head{i}.jpg", CreatedAt = DateTime.Now, UpdatedAt = DateTime.Now }); } _dbContext.SaveChanges(); } private void SeedOrders() { var orders = new[] { new Order { UserId = 1, OrderNum = "ORD001", Price = 100, UseMoney = 0, UseIntegral = 0, UseScore = 0, Status = 1, CreatedAt = DateTime.Now, UpdatedAt = DateTime.Now, GoodsId = 1, GoodsTitle = "商品1", GoodsPrice = 100, OrderTotal = 100, OrderZheTotal = 100, Zhe = 1, Num = 1, PrizeNum = 1, Addtime = (int)DateTimeOffset.Now.ToUnixTimeSeconds() }, new Order { UserId = 1, OrderNum = "ORD002", Price = 200, UseMoney = 50, UseIntegral = 0, UseScore = 0, Status = 1, CreatedAt = DateTime.Now, UpdatedAt = DateTime.Now, GoodsId = 1, GoodsTitle = "商品1", GoodsPrice = 200, OrderTotal = 200, OrderZheTotal = 200, Zhe = 1, Num = 1, PrizeNum = 1, Addtime = (int)DateTimeOffset.Now.ToUnixTimeSeconds() }, new Order { UserId = 2, OrderNum = "ORD003", Price = 500, UseMoney = 0, UseIntegral = 100, UseScore = 0, Status = 1, CreatedAt = DateTime.Now, UpdatedAt = DateTime.Now, GoodsId = 1, GoodsTitle = "商品1", GoodsPrice = 500, OrderTotal = 500, OrderZheTotal = 500, Zhe = 1, Num = 1, PrizeNum = 1, Addtime = (int)DateTimeOffset.Now.ToUnixTimeSeconds() }, new Order { UserId = 3, OrderNum = "ORD004", Price = 50, UseMoney = 0, UseIntegral = 0, UseScore = 0, Status = 1, CreatedAt = DateTime.Now, UpdatedAt = DateTime.Now, GoodsId = 1, GoodsTitle = "商品1", GoodsPrice = 50, OrderTotal = 50, OrderZheTotal = 50, Zhe = 1, Num = 1, PrizeNum = 1, Addtime = (int)DateTimeOffset.Now.ToUnixTimeSeconds() }, }; _dbContext.Orders.AddRange(orders); _dbContext.SaveChanges(); } private void SeedProfitMoney(int count) { for (int i = 1; i <= count; i++) { _dbContext.ProfitMoneys.Add(new ProfitMoney { UserId = 1, ChangeMoney = 100 * i, Money = 100 * i, Type = 1, Content = $"测试变动{i}", ShareUid = 0, CreatedAt = DateTime.Now }); } _dbContext.SaveChanges(); } private void SeedProfitMoneyForMultipleUsers() { for (int userId = 1; userId <= 3; userId++) { for (int i = 1; i <= 5; i++) { _dbContext.ProfitMoneys.Add(new ProfitMoney { UserId = userId, ChangeMoney = 100 * i, Money = 100 * i, Type = 1, Content = $"用户{userId}变动{i}", ShareUid = 0, CreatedAt = DateTime.Now }); } } _dbContext.SaveChanges(); } private void SeedProfitMoneyWithDates() { for (int i = -10; i <= 0; i++) { _dbContext.ProfitMoneys.Add(new ProfitMoney { UserId = 1, ChangeMoney = 100, Money = 100, Type = 1, Content = $"日期测试{i}", ShareUid = 0, CreatedAt = DateTime.Today.AddDays(i) }); } _dbContext.SaveChanges(); } private void SeedProfitIntegral(int count) { for (int i = 1; i <= count; i++) { _dbContext.ProfitIntegrals.Add(new ProfitIntegral { UserId = 1, ChangeMoney = 50 * i, Money = 50 * i, Type = 1, Content = $"积分变动{i}", ShareUid = 0, CreatedAt = DateTime.Now }); } _dbContext.SaveChanges(); } private void SeedProfitIntegralForMultipleUsers() { for (int userId = 1; userId <= 2; userId++) { for (int i = 1; i <= 5; i++) { _dbContext.ProfitIntegrals.Add(new ProfitIntegral { UserId = userId, ChangeMoney = 50 * i, Money = 50 * i, Type = 1, Content = $"用户{userId}积分{i}", ShareUid = 0, CreatedAt = DateTime.Now }); } } _dbContext.SaveChanges(); } private void SeedProfitScore(int count) { for (int i = 1; i <= count; i++) { _dbContext.ProfitScores.Add(new ProfitScore { UserId = 1, ChangeMoney = 10 * i, Money = 10 * i, Type = 1, Content = $"钻石变动{i}", ShareUid = 0, CreatedAt = DateTime.Now }); } _dbContext.SaveChanges(); } private void SeedProfitPay(int count) { for (int i = 1; i <= count; i++) { _dbContext.ProfitPays.Add(new ProfitPay { UserId = 1, OrderNum = $"PAY{i:D5}", ChangeMoney = 100 * i, Content = $"充值{i}", PayType = (byte)(i % 4), CreatedAt = DateTime.Now }); } _dbContext.SaveChanges(); } #endregion }