751 lines
21 KiB
C#
751 lines
21 KiB
C#
using HoneyBox.Admin.Business.Models;
|
|
using HoneyBox.Admin.Business.Models.User;
|
|
using HoneyBox.Admin.Business.Services;
|
|
using HoneyBox.Model.Data;
|
|
using HoneyBox.Model.Entities;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.EntityFrameworkCore.Diagnostics;
|
|
using Microsoft.Extensions.Logging;
|
|
using Moq;
|
|
using Xunit;
|
|
|
|
namespace HoneyBox.Tests.Services;
|
|
|
|
/// <summary>
|
|
/// UserBusinessService 单元测试
|
|
/// </summary>
|
|
public class UserBusinessServiceTests : IDisposable
|
|
{
|
|
private readonly HoneyBoxDbContext _dbContext;
|
|
private readonly Mock<ILogger<UserBusinessService>> _mockLogger;
|
|
private readonly UserBusinessService _userService;
|
|
|
|
public UserBusinessServiceTests()
|
|
{
|
|
var options = new DbContextOptionsBuilder<HoneyBoxDbContext>()
|
|
.UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString())
|
|
.ConfigureWarnings(w => w.Ignore(InMemoryEventId.TransactionIgnoredWarning))
|
|
.Options;
|
|
|
|
_dbContext = new HoneyBoxDbContext(options);
|
|
_mockLogger = new Mock<ILogger<UserBusinessService>>();
|
|
|
|
_userService = new UserBusinessService(_dbContext, _mockLogger.Object);
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
_dbContext.Dispose();
|
|
}
|
|
|
|
#region Helper Methods
|
|
|
|
private async Task<User> CreateTestUserAsync(
|
|
string nickname = "TestUser",
|
|
decimal money = 100,
|
|
decimal integral = 50,
|
|
decimal score = 30,
|
|
byte status = 1,
|
|
int isTest = 0,
|
|
int pid = 0)
|
|
{
|
|
var user = new User
|
|
{
|
|
OpenId = Guid.NewGuid().ToString("N"),
|
|
Uid = $"UID{DateTime.Now.Ticks}",
|
|
Nickname = nickname,
|
|
HeadImg = "https://example.com/avatar.png",
|
|
Mobile = "13800138000",
|
|
Money = money,
|
|
Integral = integral,
|
|
Score = score,
|
|
Status = status,
|
|
IsTest = isTest,
|
|
Pid = pid,
|
|
Vip = 1,
|
|
CreatedAt = DateTime.Now,
|
|
UpdatedAt = DateTime.Now
|
|
};
|
|
_dbContext.Users.Add(user);
|
|
await _dbContext.SaveChangesAsync();
|
|
return user;
|
|
}
|
|
|
|
private async Task<Coupon> CreateTestCouponAsync()
|
|
{
|
|
var coupon = new Coupon
|
|
{
|
|
Title = "测试优惠券",
|
|
Price = 10,
|
|
ManPrice = 100,
|
|
EffectiveDay = 30,
|
|
Status = 1,
|
|
CreatedAt = DateTime.Now
|
|
};
|
|
_dbContext.Coupons.Add(coupon);
|
|
await _dbContext.SaveChangesAsync();
|
|
return coupon;
|
|
}
|
|
|
|
private async Task<(Good goods, GoodsItem item)> CreateTestGoodsWithItemAsync()
|
|
{
|
|
var goods = new Good
|
|
{
|
|
Title = "测试盒子",
|
|
Price = 10,
|
|
ImgUrl = "https://example.com/goods.png",
|
|
ImgUrlDetail = "https://example.com/goods_detail.png",
|
|
Type = 1,
|
|
Status = 1,
|
|
Stock = 100,
|
|
SaleStock = 0,
|
|
CreatedAt = DateTime.Now,
|
|
UpdatedAt = DateTime.Now
|
|
};
|
|
_dbContext.Goods.Add(goods);
|
|
await _dbContext.SaveChangesAsync();
|
|
|
|
var item = new GoodsItem
|
|
{
|
|
GoodsId = goods.Id,
|
|
Title = "测试奖品",
|
|
ImgUrl = "https://example.com/item.png",
|
|
Price = 50,
|
|
Money = 30,
|
|
Stock = 10,
|
|
SurplusStock = 10,
|
|
Type = 1,
|
|
ShangId = 1,
|
|
UpdatedAt = DateTime.Now
|
|
};
|
|
_dbContext.GoodsItems.Add(item);
|
|
await _dbContext.SaveChangesAsync();
|
|
|
|
return (goods, item);
|
|
}
|
|
|
|
private async Task<VipLevel> CreateTestVipLevelAsync()
|
|
{
|
|
var vipLevel = new VipLevel
|
|
{
|
|
Level = 1,
|
|
Title = "VIP1",
|
|
Number = 100,
|
|
CreatedAt = DateTime.Now,
|
|
UpdatedAt = DateTime.Now
|
|
};
|
|
_dbContext.VipLevels.Add(vipLevel);
|
|
await _dbContext.SaveChangesAsync();
|
|
return vipLevel;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region GetUserListAsync Tests
|
|
|
|
[Fact]
|
|
public async Task GetUserListAsync_ReturnsPagedResult()
|
|
{
|
|
// Arrange
|
|
await CreateTestUserAsync("User1");
|
|
await CreateTestUserAsync("User2");
|
|
await CreateTestUserAsync("User3");
|
|
|
|
var request = new UserListRequest { Page = 1, PageSize = 2 };
|
|
|
|
// Act
|
|
var result = await _userService.GetUserListAsync(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);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetUserListAsync_WithNicknameFilter_ReturnsFilteredResult()
|
|
{
|
|
// Arrange
|
|
await CreateTestUserAsync("Alice");
|
|
await CreateTestUserAsync("Bob");
|
|
await CreateTestUserAsync("AliceSmith");
|
|
|
|
var request = new UserListRequest { Nickname = "Alice" };
|
|
|
|
// Act
|
|
var result = await _userService.GetUserListAsync(request);
|
|
|
|
// Assert
|
|
Assert.Equal(2, result.Total);
|
|
Assert.All(result.List, u => Assert.Contains("Alice", u.Nickname!));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetUserListAsync_WithParentIdFilter_ReturnsSubordinates()
|
|
{
|
|
// Arrange
|
|
var parent = await CreateTestUserAsync("Parent");
|
|
await CreateTestUserAsync("Child1", pid: parent.Id);
|
|
await CreateTestUserAsync("Child2", pid: parent.Id);
|
|
await CreateTestUserAsync("Other");
|
|
|
|
var request = new UserListRequest { ParentId = parent.Id };
|
|
|
|
// Act
|
|
var result = await _userService.GetUserListAsync(request);
|
|
|
|
// Assert
|
|
Assert.Equal(2, result.Total);
|
|
Assert.All(result.List, u => Assert.Equal(parent.Id, u.ParentId));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetUserListAsync_WithDateRangeFilter_ReturnsFilteredResult()
|
|
{
|
|
// Arrange
|
|
var user1 = await CreateTestUserAsync("User1");
|
|
user1.CreatedAt = DateTime.Now.AddDays(-5);
|
|
var user2 = await CreateTestUserAsync("User2");
|
|
user2.CreatedAt = DateTime.Now.AddDays(-1);
|
|
await _dbContext.SaveChangesAsync();
|
|
|
|
var request = new UserListRequest
|
|
{
|
|
StartDate = DateTime.Now.AddDays(-3),
|
|
EndDate = DateTime.Now
|
|
};
|
|
|
|
// Act
|
|
var result = await _userService.GetUserListAsync(request);
|
|
|
|
// Assert
|
|
Assert.Equal(1, result.Total);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region GetUserDetailAsync Tests
|
|
|
|
[Fact]
|
|
public async Task GetUserDetailAsync_WithExistingUser_ReturnsDetail()
|
|
{
|
|
// Arrange
|
|
var user = await CreateTestUserAsync("DetailUser", money: 200, integral: 100, score: 50);
|
|
|
|
// Act
|
|
var result = await _userService.GetUserDetailAsync(user.Id);
|
|
|
|
// Assert
|
|
Assert.NotNull(result);
|
|
Assert.Equal(user.Id, result.Id);
|
|
Assert.Equal("DetailUser", result.Nickname);
|
|
Assert.Equal(200, result.Balance);
|
|
Assert.Equal(100, result.Integral);
|
|
Assert.Equal(50, result.Diamond);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetUserDetailAsync_WithNonExistingUser_ReturnsNull()
|
|
{
|
|
// Act
|
|
var result = await _userService.GetUserDetailAsync(99999);
|
|
|
|
// Assert
|
|
Assert.Null(result);
|
|
}
|
|
|
|
#endregion
|
|
|
|
|
|
#region ChangeUserMoneyAsync Tests
|
|
|
|
[Fact]
|
|
public async Task ChangeUserMoneyAsync_AddBalance_IncreasesBalance()
|
|
{
|
|
// Arrange
|
|
var user = await CreateTestUserAsync(money: 100);
|
|
var request = new UserMoneyChangeRequest
|
|
{
|
|
Type = MoneyChangeType.Balance,
|
|
Amount = 50,
|
|
Operation = OperationType.Add,
|
|
Remark = "测试增加"
|
|
};
|
|
|
|
// Act
|
|
var result = await _userService.ChangeUserMoneyAsync(user.Id, request, 1);
|
|
|
|
// Assert
|
|
Assert.True(result);
|
|
var updatedUser = await _dbContext.Users.FindAsync(user.Id);
|
|
Assert.Equal(150, updatedUser!.Money);
|
|
|
|
// 验证记录了变动日志
|
|
var profitLog = await _dbContext.ProfitMoneys.FirstOrDefaultAsync(p => p.UserId == user.Id);
|
|
Assert.NotNull(profitLog);
|
|
Assert.Equal(50, profitLog.ChangeMoney);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ChangeUserMoneyAsync_SubtractBalance_DecreasesBalance()
|
|
{
|
|
// Arrange
|
|
var user = await CreateTestUserAsync(money: 100);
|
|
var request = new UserMoneyChangeRequest
|
|
{
|
|
Type = MoneyChangeType.Balance,
|
|
Amount = 30,
|
|
Operation = OperationType.Subtract
|
|
};
|
|
|
|
// Act
|
|
var result = await _userService.ChangeUserMoneyAsync(user.Id, request, 1);
|
|
|
|
// Assert
|
|
Assert.True(result);
|
|
var updatedUser = await _dbContext.Users.FindAsync(user.Id);
|
|
Assert.Equal(70, updatedUser!.Money);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ChangeUserMoneyAsync_SubtractMoreThanBalance_ThrowsException()
|
|
{
|
|
// Arrange
|
|
var user = await CreateTestUserAsync(money: 50);
|
|
var request = new UserMoneyChangeRequest
|
|
{
|
|
Type = MoneyChangeType.Balance,
|
|
Amount = 100,
|
|
Operation = OperationType.Subtract
|
|
};
|
|
|
|
// Act & Assert
|
|
var ex = await Assert.ThrowsAsync<BusinessException>(
|
|
() => _userService.ChangeUserMoneyAsync(user.Id, request, 1));
|
|
Assert.Equal(BusinessErrorCodes.ValidationFailed, ex.Code);
|
|
Assert.Contains("不足", ex.Message);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ChangeUserMoneyAsync_AddIntegral_IncreasesIntegral()
|
|
{
|
|
// Arrange
|
|
var user = await CreateTestUserAsync(integral: 50);
|
|
var request = new UserMoneyChangeRequest
|
|
{
|
|
Type = MoneyChangeType.Integral,
|
|
Amount = 25,
|
|
Operation = OperationType.Add
|
|
};
|
|
|
|
// Act
|
|
var result = await _userService.ChangeUserMoneyAsync(user.Id, request, 1);
|
|
|
|
// Assert
|
|
Assert.True(result);
|
|
var updatedUser = await _dbContext.Users.FindAsync(user.Id);
|
|
Assert.Equal(75, updatedUser!.Integral);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ChangeUserMoneyAsync_AddDiamond_IncreasesDiamond()
|
|
{
|
|
// Arrange
|
|
var user = await CreateTestUserAsync(score: 30);
|
|
var request = new UserMoneyChangeRequest
|
|
{
|
|
Type = MoneyChangeType.Diamond,
|
|
Amount = 20,
|
|
Operation = OperationType.Add
|
|
};
|
|
|
|
// Act
|
|
var result = await _userService.ChangeUserMoneyAsync(user.Id, request, 1);
|
|
|
|
// Assert
|
|
Assert.True(result);
|
|
var updatedUser = await _dbContext.Users.FindAsync(user.Id);
|
|
Assert.Equal(50, updatedUser!.Score);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ChangeUserMoneyAsync_NonExistingUser_ThrowsException()
|
|
{
|
|
// Arrange
|
|
var request = new UserMoneyChangeRequest
|
|
{
|
|
Type = MoneyChangeType.Balance,
|
|
Amount = 50,
|
|
Operation = OperationType.Add
|
|
};
|
|
|
|
// Act & Assert
|
|
var ex = await Assert.ThrowsAsync<BusinessException>(
|
|
() => _userService.ChangeUserMoneyAsync(99999, request, 1));
|
|
Assert.Equal(BusinessErrorCodes.NotFound, ex.Code);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region SetUserStatusAsync Tests
|
|
|
|
[Fact]
|
|
public async Task SetUserStatusAsync_BanUser_SetsStatusToDisabled()
|
|
{
|
|
// Arrange
|
|
var user = await CreateTestUserAsync(status: 1);
|
|
|
|
// Act
|
|
var result = await _userService.SetUserStatusAsync(user.Id, 0);
|
|
|
|
// Assert
|
|
Assert.True(result);
|
|
var updatedUser = await _dbContext.Users.FindAsync(user.Id);
|
|
Assert.Equal(0, updatedUser!.Status);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task SetUserStatusAsync_UnbanUser_SetsStatusToEnabled()
|
|
{
|
|
// Arrange
|
|
var user = await CreateTestUserAsync(status: 0);
|
|
|
|
// Act
|
|
var result = await _userService.SetUserStatusAsync(user.Id, 1);
|
|
|
|
// Assert
|
|
Assert.True(result);
|
|
var updatedUser = await _dbContext.Users.FindAsync(user.Id);
|
|
Assert.Equal(1, updatedUser!.Status);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task SetUserStatusAsync_NonExistingUser_ThrowsException()
|
|
{
|
|
// Act & Assert
|
|
var ex = await Assert.ThrowsAsync<BusinessException>(
|
|
() => _userService.SetUserStatusAsync(99999, 0));
|
|
Assert.Equal(BusinessErrorCodes.NotFound, ex.Code);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region SetTestAccountAsync Tests
|
|
|
|
[Fact]
|
|
public async Task SetTestAccountAsync_SetAsTest_UpdatesIsTest()
|
|
{
|
|
// Arrange
|
|
var user = await CreateTestUserAsync(isTest: 0);
|
|
|
|
// Act
|
|
var result = await _userService.SetTestAccountAsync(user.Id, 1);
|
|
|
|
// Assert
|
|
Assert.True(result);
|
|
var updatedUser = await _dbContext.Users.FindAsync(user.Id);
|
|
Assert.Equal(1, updatedUser!.IsTest);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task SetTestAccountAsync_RemoveTest_UpdatesIsTest()
|
|
{
|
|
// Arrange
|
|
var user = await CreateTestUserAsync(isTest: 1);
|
|
|
|
// Act
|
|
var result = await _userService.SetTestAccountAsync(user.Id, 0);
|
|
|
|
// Assert
|
|
Assert.True(result);
|
|
var updatedUser = await _dbContext.Users.FindAsync(user.Id);
|
|
Assert.Equal(0, updatedUser!.IsTest);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ClearMobileAsync Tests
|
|
|
|
[Fact]
|
|
public async Task ClearMobileAsync_ClearsMobileAndSavesOld()
|
|
{
|
|
// Arrange
|
|
var user = await CreateTestUserAsync();
|
|
var originalMobile = user.Mobile;
|
|
|
|
// Act
|
|
var result = await _userService.ClearMobileAsync(user.Id);
|
|
|
|
// Assert
|
|
Assert.True(result);
|
|
var updatedUser = await _dbContext.Users.FindAsync(user.Id);
|
|
Assert.Null(updatedUser!.Mobile);
|
|
Assert.Equal(originalMobile, updatedUser.OldMobile);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ClearWeChatAsync Tests
|
|
|
|
[Fact]
|
|
public async Task ClearWeChatAsync_GeneratesNewOpenId()
|
|
{
|
|
// Arrange
|
|
var user = await CreateTestUserAsync();
|
|
var originalOpenId = user.OpenId;
|
|
|
|
// Act
|
|
var result = await _userService.ClearWeChatAsync(user.Id);
|
|
|
|
// Assert
|
|
Assert.True(result);
|
|
var updatedUser = await _dbContext.Users.FindAsync(user.Id);
|
|
Assert.NotEqual(originalOpenId, updatedUser!.OpenId);
|
|
Assert.StartsWith("cleared_", updatedUser.OpenId);
|
|
Assert.Null(updatedUser.UnionId);
|
|
Assert.Null(updatedUser.GzhOpenId);
|
|
}
|
|
|
|
#endregion
|
|
|
|
|
|
#region GiftCouponAsync Tests
|
|
|
|
[Fact]
|
|
public async Task GiftCouponAsync_CreatesCouponReceiveRecords()
|
|
{
|
|
// Arrange
|
|
var user = await CreateTestUserAsync();
|
|
var coupon = await CreateTestCouponAsync();
|
|
var request = new GiftCouponRequest
|
|
{
|
|
CouponId = coupon.Id,
|
|
Quantity = 3
|
|
};
|
|
|
|
// Act
|
|
var result = await _userService.GiftCouponAsync(user.Id, request);
|
|
|
|
// Assert
|
|
Assert.True(result);
|
|
var receives = await _dbContext.CouponReceives
|
|
.Where(r => r.UserId == user.Id && r.CouponId == coupon.Id)
|
|
.ToListAsync();
|
|
Assert.Equal(3, receives.Count);
|
|
Assert.All(receives, r =>
|
|
{
|
|
Assert.Equal(coupon.Title, r.Title);
|
|
Assert.Equal(coupon.Price, r.Price);
|
|
Assert.Equal((byte)1, r.Status);
|
|
Assert.Equal((byte?)0, r.State);
|
|
});
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GiftCouponAsync_NonExistingUser_ThrowsException()
|
|
{
|
|
// Arrange
|
|
var coupon = await CreateTestCouponAsync();
|
|
var request = new GiftCouponRequest { CouponId = coupon.Id, Quantity = 1 };
|
|
|
|
// Act & Assert
|
|
var ex = await Assert.ThrowsAsync<BusinessException>(
|
|
() => _userService.GiftCouponAsync(99999, request));
|
|
Assert.Equal(BusinessErrorCodes.NotFound, ex.Code);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GiftCouponAsync_NonExistingCoupon_ThrowsException()
|
|
{
|
|
// Arrange
|
|
var user = await CreateTestUserAsync();
|
|
var request = new GiftCouponRequest { CouponId = 99999, Quantity = 1 };
|
|
|
|
// Act & Assert
|
|
var ex = await Assert.ThrowsAsync<BusinessException>(
|
|
() => _userService.GiftCouponAsync(user.Id, request));
|
|
Assert.Equal(BusinessErrorCodes.NotFound, ex.Code);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region GiftCardAsync Tests
|
|
|
|
[Fact]
|
|
public async Task GiftCardAsync_CreatesOrderAndOrderItems()
|
|
{
|
|
// Arrange
|
|
var user = await CreateTestUserAsync();
|
|
var (goods, item) = await CreateTestGoodsWithItemAsync();
|
|
var request = new GiftCardRequest
|
|
{
|
|
GoodsId = goods.Id,
|
|
GoodsListId = item.Id,
|
|
Quantity = 2
|
|
};
|
|
|
|
// Act
|
|
var result = await _userService.GiftCardAsync(user.Id, request);
|
|
|
|
// Assert
|
|
Assert.True(result);
|
|
|
|
// 验证订单
|
|
var order = await _dbContext.Orders
|
|
.FirstOrDefaultAsync(o => o.UserId == user.Id && o.OrderType == 9);
|
|
Assert.NotNull(order);
|
|
Assert.Equal(0, order.Price);
|
|
Assert.Equal(2, order.Num);
|
|
|
|
// 验证订单详情
|
|
var orderItems = await _dbContext.OrderItems
|
|
.Where(oi => oi.OrderId == order.Id)
|
|
.ToListAsync();
|
|
Assert.Equal(2, orderItems.Count);
|
|
Assert.All(orderItems, oi =>
|
|
{
|
|
Assert.Equal(item.Title, oi.GoodslistTitle);
|
|
Assert.Equal(9, oi.OrderType);
|
|
Assert.NotNull(oi.PrizeCode);
|
|
});
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GiftCardAsync_NonExistingGoods_ThrowsException()
|
|
{
|
|
// Arrange
|
|
var user = await CreateTestUserAsync();
|
|
var request = new GiftCardRequest { GoodsId = 99999, GoodsListId = 1, Quantity = 1 };
|
|
|
|
// Act & Assert
|
|
var ex = await Assert.ThrowsAsync<BusinessException>(
|
|
() => _userService.GiftCardAsync(user.Id, request));
|
|
Assert.Equal(BusinessErrorCodes.NotFound, ex.Code);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region VIP Management Tests
|
|
|
|
[Fact]
|
|
public async Task GetVipLevelsAsync_ReturnsAllLevels()
|
|
{
|
|
// Arrange
|
|
await CreateTestVipLevelAsync();
|
|
var vip2 = new VipLevel
|
|
{
|
|
Level = 2,
|
|
Title = "VIP2",
|
|
Number = 500,
|
|
CreatedAt = DateTime.Now,
|
|
UpdatedAt = DateTime.Now
|
|
};
|
|
_dbContext.VipLevels.Add(vip2);
|
|
await _dbContext.SaveChangesAsync();
|
|
|
|
// Act
|
|
var result = await _userService.GetVipLevelsAsync();
|
|
|
|
// Assert
|
|
Assert.Equal(2, result.Count);
|
|
Assert.Equal("VIP1", result[0].Title);
|
|
Assert.Equal("VIP2", result[1].Title);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task UpdateVipLevelAsync_UpdatesLevel()
|
|
{
|
|
// Arrange
|
|
var vipLevel = await CreateTestVipLevelAsync();
|
|
var request = new VipLevelUpdateRequest
|
|
{
|
|
Title = "Updated VIP",
|
|
Number = 200
|
|
};
|
|
|
|
// Act
|
|
var result = await _userService.UpdateVipLevelAsync(vipLevel.Id, request);
|
|
|
|
// Assert
|
|
Assert.True(result);
|
|
var updated = await _dbContext.VipLevels.FindAsync(vipLevel.Id);
|
|
Assert.Equal("Updated VIP", updated!.Title);
|
|
Assert.Equal(200, updated.Number);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task UpdateVipLevelAsync_NonExistingLevel_ThrowsException()
|
|
{
|
|
// Arrange
|
|
var request = new VipLevelUpdateRequest { Title = "Test", Number = 100 };
|
|
|
|
// Act & Assert
|
|
var ex = await Assert.ThrowsAsync<BusinessException>(
|
|
() => _userService.UpdateVipLevelAsync(99999, request));
|
|
Assert.Equal(BusinessErrorCodes.NotFound, ex.Code);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region GetSubordinateUsersAsync Tests
|
|
|
|
[Fact]
|
|
public async Task GetSubordinateUsersAsync_ReturnsSubordinates()
|
|
{
|
|
// Arrange
|
|
var parent = await CreateTestUserAsync("Parent");
|
|
await CreateTestUserAsync("Child1", pid: parent.Id);
|
|
await CreateTestUserAsync("Child2", pid: parent.Id);
|
|
|
|
// Act
|
|
var result = await _userService.GetSubordinateUsersAsync(parent.Id, 1, 10);
|
|
|
|
// Assert
|
|
Assert.Equal(2, result.Total);
|
|
Assert.Equal(2, result.List.Count);
|
|
Assert.All(result.List, u => Assert.Equal(parent.Id, u.ParentId));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetSubordinateUsersAsync_NonExistingUser_ThrowsException()
|
|
{
|
|
// Act & Assert
|
|
var ex = await Assert.ThrowsAsync<BusinessException>(
|
|
() => _userService.GetSubordinateUsersAsync(99999, 1, 10));
|
|
Assert.Equal(BusinessErrorCodes.NotFound, ex.Code);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region GetUserProfitLossAsync Tests
|
|
|
|
[Fact]
|
|
public async Task GetUserProfitLossAsync_ReturnsStatistics()
|
|
{
|
|
// Arrange
|
|
var user = await CreateTestUserAsync(money: 100, integral: 50, score: 30);
|
|
|
|
// Act
|
|
var result = await _userService.GetUserProfitLossAsync(user.Id, null);
|
|
|
|
// Assert
|
|
Assert.Equal(user.Id, result.UserId);
|
|
Assert.Equal(100, result.CurrentBalance);
|
|
Assert.Equal(50, result.CurrentIntegral);
|
|
Assert.Equal(30, result.CurrentDiamond);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetUserProfitLossAsync_NonExistingUser_ThrowsException()
|
|
{
|
|
// Act & Assert
|
|
var ex = await Assert.ThrowsAsync<BusinessException>(
|
|
() => _userService.GetUserProfitLossAsync(99999, null));
|
|
Assert.Equal(BusinessErrorCodes.NotFound, ex.Code);
|
|
}
|
|
|
|
#endregion
|
|
}
|