638 lines
23 KiB
C#
638 lines
23 KiB
C#
using HoneyBox.Core.Interfaces;
|
||
using HoneyBox.Core.Services;
|
||
using HoneyBox.Model.Data;
|
||
using HoneyBox.Model.Entities;
|
||
using HoneyBox.Model.Models.Goods;
|
||
using Microsoft.EntityFrameworkCore;
|
||
using Microsoft.Extensions.Logging;
|
||
using Moq;
|
||
using Xunit;
|
||
|
||
namespace HoneyBox.Tests.Integration;
|
||
|
||
/// <summary>
|
||
/// 商品服务集成测试
|
||
/// 测试完整的商品查询流程
|
||
/// Requirements: 1.1-1.6, 2.1-2.7
|
||
/// </summary>
|
||
public class GoodsServiceIntegrationTests
|
||
{
|
||
private HoneyBoxDbContext CreateInMemoryDbContext()
|
||
{
|
||
var options = new DbContextOptionsBuilder<HoneyBoxDbContext>()
|
||
.UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString())
|
||
.Options;
|
||
|
||
return new HoneyBoxDbContext(options);
|
||
}
|
||
|
||
private GoodsService CreateGoodsService(HoneyBoxDbContext dbContext, IGoodsCacheService? cacheService = null)
|
||
{
|
||
var mockLogger = new Mock<ILogger<GoodsService>>();
|
||
var mockCacheService = cacheService ?? CreateMockCacheService();
|
||
return new GoodsService(dbContext, mockCacheService, mockLogger.Object);
|
||
}
|
||
|
||
private IGoodsCacheService CreateMockCacheService()
|
||
{
|
||
var mock = new Mock<IGoodsCacheService>();
|
||
mock.Setup(x => x.GetJoinCountAsync(It.IsAny<int>())).ReturnsAsync(-1);
|
||
mock.Setup(x => x.SetJoinCountAsync(It.IsAny<int>(), It.IsAny<int>())).Returns(Task.CompletedTask);
|
||
return mock.Object;
|
||
}
|
||
|
||
#region 商品列表测试 (Requirements 1.1-1.6)
|
||
|
||
/// <summary>
|
||
/// 测试商品列表查询 - 返回分页商品
|
||
/// Requirements: 1.1
|
||
/// </summary>
|
||
[Fact]
|
||
public async Task GetGoodsList_WithTypeFilter_ReturnsMatchingGoods()
|
||
{
|
||
// Arrange
|
||
var dbContext = CreateInMemoryDbContext();
|
||
var service = CreateGoodsService(dbContext);
|
||
|
||
// 添加商品类型
|
||
await dbContext.GoodsTypes.AddAsync(new GoodsType { Value = 2, Name = "无限赏", FlName = "无限赏", CornerText = "无限赏" });
|
||
await dbContext.GoodsTypes.AddAsync(new GoodsType { Value = 6, Name = "全局赏", FlName = "全局赏", CornerText = "全局赏" });
|
||
await dbContext.SaveChangesAsync();
|
||
|
||
// 添加测试商品
|
||
var goods = new List<Good>
|
||
{
|
||
new() { Id = 1, Title = "商品1", Type = 2, Status = 1, ShowIs = 0, Price = 10, Stock = 10, Sort = 1, ImgUrl = "img1.jpg", ImgUrlDetail = "detail1.jpg" },
|
||
new() { Id = 2, Title = "商品2", Type = 2, Status = 1, ShowIs = 0, Price = 20, Stock = 20, Sort = 2, ImgUrl = "img2.jpg", ImgUrlDetail = "detail2.jpg" },
|
||
new() { Id = 3, Title = "商品3", Type = 6, Status = 1, ShowIs = 0, Price = 30, Stock = 30, Sort = 3, ImgUrl = "img3.jpg", ImgUrlDetail = "detail3.jpg" }
|
||
};
|
||
await dbContext.Goods.AddRangeAsync(goods);
|
||
await dbContext.SaveChangesAsync();
|
||
|
||
// Act - 查询类型2的商品
|
||
var request = new GoodsListRequest { Type = 2, Page = 1, PageSize = 10 };
|
||
var result = await service.GetGoodsListAsync(request, 0);
|
||
|
||
// Assert
|
||
Assert.NotNull(result);
|
||
Assert.Equal(2, result.Total);
|
||
Assert.All(result.Data, g => Assert.Equal(2, g.Type));
|
||
}
|
||
|
||
/// <summary>
|
||
/// 测试商品列表查询 - type=-1返回默认类型商品
|
||
/// Requirements: 1.2
|
||
/// </summary>
|
||
[Fact]
|
||
public async Task GetGoodsList_TypeMinusOne_ReturnsDefaultTypeGoods()
|
||
{
|
||
// Arrange
|
||
var dbContext = CreateInMemoryDbContext();
|
||
var service = CreateGoodsService(dbContext);
|
||
|
||
// 添加商品类型
|
||
await dbContext.GoodsTypes.AddAsync(new GoodsType { Value = 2, Name = "无限赏", FlName = "无限赏", CornerText = "无限赏" });
|
||
await dbContext.GoodsTypes.AddAsync(new GoodsType { Value = 6, Name = "全局赏", FlName = "全局赏", CornerText = "全局赏" });
|
||
await dbContext.GoodsTypes.AddAsync(new GoodsType { Value = 8, Name = "领主赏", FlName = "领主赏", CornerText = "领主赏" });
|
||
await dbContext.GoodsTypes.AddAsync(new GoodsType { Value = 16, Name = "其他", FlName = "其他", CornerText = "其他" });
|
||
await dbContext.SaveChangesAsync();
|
||
|
||
// 添加测试商品 - 默认类型: 2, 6, 8, 16
|
||
var goods = new List<Good>
|
||
{
|
||
new() { Id = 1, Title = "商品1", Type = 2, Status = 1, ShowIs = 0, Price = 10, Stock = 10, Sort = 1, ImgUrl = "img1.jpg", ImgUrlDetail = "detail1.jpg" },
|
||
new() { Id = 2, Title = "商品2", Type = 6, Status = 1, ShowIs = 0, Price = 20, Stock = 20, Sort = 2, ImgUrl = "img2.jpg", ImgUrlDetail = "detail2.jpg" },
|
||
new() { Id = 3, Title = "商品3", Type = 1, Status = 1, ShowIs = 0, Price = 30, Stock = 30, Sort = 3, ImgUrl = "img3.jpg", ImgUrlDetail = "detail3.jpg" } // 非默认类型
|
||
};
|
||
await dbContext.Goods.AddRangeAsync(goods);
|
||
await dbContext.SaveChangesAsync();
|
||
|
||
// Act - type=-1 返回默认类型
|
||
var request = new GoodsListRequest { Type = -1, Page = 1, PageSize = 10 };
|
||
var result = await service.GetGoodsListAsync(request, 0);
|
||
|
||
// Assert
|
||
Assert.NotNull(result);
|
||
Assert.Equal(2, result.Total); // 只有类型2和6的商品
|
||
Assert.All(result.Data, g => Assert.Contains(g.Type, new[] { 2, 6, 8, 16 }));
|
||
}
|
||
|
||
/// <summary>
|
||
/// 测试商品列表查询 - 过滤非上架商品
|
||
/// Requirements: 1.4
|
||
/// </summary>
|
||
[Fact]
|
||
public async Task GetGoodsList_FiltersInactiveGoods()
|
||
{
|
||
// Arrange
|
||
var dbContext = CreateInMemoryDbContext();
|
||
var service = CreateGoodsService(dbContext);
|
||
|
||
await dbContext.GoodsTypes.AddAsync(new GoodsType { Value = 2, Name = "无限赏", FlName = "无限赏", CornerText = "无限赏" });
|
||
await dbContext.SaveChangesAsync();
|
||
|
||
var goods = new List<Good>
|
||
{
|
||
new() { Id = 1, Title = "上架商品", Type = 2, Status = 1, ShowIs = 0, Price = 10, Stock = 10, Sort = 1, ImgUrl = "img1.jpg", ImgUrlDetail = "detail1.jpg" },
|
||
new() { Id = 2, Title = "下架商品", Type = 2, Status = 0, ShowIs = 0, Price = 20, Stock = 20, Sort = 2, ImgUrl = "img2.jpg", ImgUrlDetail = "detail2.jpg" }
|
||
};
|
||
await dbContext.Goods.AddRangeAsync(goods);
|
||
await dbContext.SaveChangesAsync();
|
||
|
||
// Act
|
||
var request = new GoodsListRequest { Type = 2, Page = 1, PageSize = 10 };
|
||
var result = await service.GetGoodsListAsync(request, 0);
|
||
|
||
// Assert
|
||
Assert.Single(result.Data);
|
||
Assert.Equal("上架商品", result.Data[0].Title);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 测试商品列表查询 - 解锁金额过滤
|
||
/// Requirements: 1.5
|
||
/// </summary>
|
||
[Fact]
|
||
public async Task GetGoodsList_FiltersUnlockAmountForAnonymousUser()
|
||
{
|
||
// Arrange
|
||
var dbContext = CreateInMemoryDbContext();
|
||
var service = CreateGoodsService(dbContext);
|
||
|
||
await dbContext.GoodsTypes.AddAsync(new GoodsType { Value = 2, Name = "无限赏", FlName = "无限赏", CornerText = "无限赏" });
|
||
await dbContext.SaveChangesAsync();
|
||
|
||
var goods = new List<Good>
|
||
{
|
||
new() { Id = 1, Title = "无门槛商品", Type = 2, Status = 1, ShowIs = 0, Price = 10, Stock = 10, Sort = 1, UnlockAmount = 0, ImgUrl = "img1.jpg", ImgUrlDetail = "detail1.jpg" },
|
||
new() { Id = 2, Title = "有门槛商品", Type = 2, Status = 1, ShowIs = 0, Price = 20, Stock = 20, Sort = 2, UnlockAmount = 100, ImgUrl = "img2.jpg", ImgUrlDetail = "detail2.jpg" }
|
||
};
|
||
await dbContext.Goods.AddRangeAsync(goods);
|
||
await dbContext.SaveChangesAsync();
|
||
|
||
// Act - 未登录用户 (userId=0)
|
||
var request = new GoodsListRequest { Type = 2, Page = 1, PageSize = 10 };
|
||
var result = await service.GetGoodsListAsync(request, 0);
|
||
|
||
// Assert - 只能看到无门槛商品
|
||
Assert.Single(result.Data);
|
||
Assert.Equal("无门槛商品", result.Data[0].Title);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 测试商品列表查询 - 排序正确性
|
||
/// Requirements: 1.6
|
||
/// </summary>
|
||
[Fact]
|
||
public async Task GetGoodsList_SortsBySortDescThenIdDesc()
|
||
{
|
||
// Arrange
|
||
var dbContext = CreateInMemoryDbContext();
|
||
var service = CreateGoodsService(dbContext);
|
||
|
||
await dbContext.GoodsTypes.AddAsync(new GoodsType { Value = 2, Name = "无限赏", FlName = "无限赏", CornerText = "无限赏" });
|
||
await dbContext.SaveChangesAsync();
|
||
|
||
var goods = new List<Good>
|
||
{
|
||
new() { Id = 1, Title = "商品1", Type = 2, Status = 1, ShowIs = 0, Price = 10, Stock = 10, Sort = 1, ImgUrl = "img1.jpg", ImgUrlDetail = "detail1.jpg" },
|
||
new() { Id = 2, Title = "商品2", Type = 2, Status = 1, ShowIs = 0, Price = 20, Stock = 20, Sort = 2, ImgUrl = "img2.jpg", ImgUrlDetail = "detail2.jpg" },
|
||
new() { Id = 3, Title = "商品3", Type = 2, Status = 1, ShowIs = 0, Price = 30, Stock = 30, Sort = 2, ImgUrl = "img3.jpg", ImgUrlDetail = "detail3.jpg" }
|
||
};
|
||
await dbContext.Goods.AddRangeAsync(goods);
|
||
await dbContext.SaveChangesAsync();
|
||
|
||
// Act
|
||
var request = new GoodsListRequest { Type = 2, Page = 1, PageSize = 10 };
|
||
var result = await service.GetGoodsListAsync(request, 0);
|
||
|
||
// Assert - 按sort DESC, id DESC排序
|
||
Assert.Equal(3, result.Data.Count);
|
||
Assert.Equal(3, result.Data[0].Id); // sort=2, id=3
|
||
Assert.Equal(2, result.Data[1].Id); // sort=2, id=2
|
||
Assert.Equal(1, result.Data[2].Id); // sort=1, id=1
|
||
}
|
||
|
||
/// <summary>
|
||
/// 测试商品列表查询 - 分页功能
|
||
/// Requirements: 1.1
|
||
/// </summary>
|
||
[Fact]
|
||
public async Task GetGoodsList_PaginationWorksCorrectly()
|
||
{
|
||
// Arrange
|
||
var dbContext = CreateInMemoryDbContext();
|
||
var service = CreateGoodsService(dbContext);
|
||
|
||
await dbContext.GoodsTypes.AddAsync(new GoodsType { Value = 2, Name = "无限赏", FlName = "无限赏", CornerText = "无限赏" });
|
||
await dbContext.SaveChangesAsync();
|
||
|
||
// 添加15条商品
|
||
var goods = Enumerable.Range(1, 15).Select(i => new Good
|
||
{
|
||
Id = i,
|
||
Title = $"商品{i}",
|
||
Type = 2,
|
||
Status = 1,
|
||
ShowIs = 0,
|
||
Price = i * 10,
|
||
Stock = 10,
|
||
Sort = i,
|
||
ImgUrl = $"img{i}.jpg",
|
||
ImgUrlDetail = $"detail{i}.jpg"
|
||
}).ToList();
|
||
await dbContext.Goods.AddRangeAsync(goods);
|
||
await dbContext.SaveChangesAsync();
|
||
|
||
// Act - 第一页
|
||
var page1Request = new GoodsListRequest { Type = 2, Page = 1, PageSize = 10 };
|
||
var page1 = await service.GetGoodsListAsync(page1Request, 0);
|
||
|
||
// Act - 第二页
|
||
var page2Request = new GoodsListRequest { Type = 2, Page = 2, PageSize = 10 };
|
||
var page2 = await service.GetGoodsListAsync(page2Request, 0);
|
||
|
||
// Assert
|
||
Assert.Equal(15, page1.Total);
|
||
Assert.Equal(2, page1.LastPage);
|
||
Assert.Equal(10, page1.Data.Count);
|
||
Assert.Equal(5, page2.Data.Count);
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 商品详情测试 (Requirements 2.1-2.7)
|
||
|
||
/// <summary>
|
||
/// 测试商品详情查询 - 返回完整商品信息
|
||
/// Requirements: 2.1
|
||
/// </summary>
|
||
[Fact]
|
||
public async Task GetGoodsDetail_ReturnsCompleteGoodsInfo()
|
||
{
|
||
// Arrange
|
||
var dbContext = CreateInMemoryDbContext();
|
||
var service = CreateGoodsService(dbContext);
|
||
|
||
// 添加商品类型
|
||
await dbContext.GoodsTypes.AddAsync(new GoodsType { Value = 2, Name = "无限赏", FlName = "无限赏", CornerText = "无限赏" });
|
||
await dbContext.SaveChangesAsync();
|
||
|
||
// 添加商品
|
||
var goods = new Good
|
||
{
|
||
Id = 1,
|
||
Title = "测试商品",
|
||
Type = 2,
|
||
Status = 1,
|
||
ShowIs = 0,
|
||
Price = 10,
|
||
Stock = 5,
|
||
SaleStock = 2,
|
||
LockIs = 0,
|
||
ImgUrl = "img.jpg",
|
||
ImgUrlDetail = "detail.jpg",
|
||
CouponIs = 1,
|
||
CouponPro = 10,
|
||
IntegralIs = 1,
|
||
RageIs = 0,
|
||
LingzhuIs = 0,
|
||
DailyXiangou = 0,
|
||
QuanjuXiangou = 0
|
||
};
|
||
await dbContext.Goods.AddAsync(goods);
|
||
|
||
// 添加奖品等级
|
||
await dbContext.PrizeLevels.AddAsync(new PrizeLevel { Id = 10, Title = "A赏", Color = "#FF0000" });
|
||
await dbContext.SaveChangesAsync();
|
||
|
||
// 添加奖品
|
||
var goodsItem = new GoodsItem
|
||
{
|
||
Id = 1,
|
||
GoodsId = 1,
|
||
Num = 1,
|
||
Title = "奖品1",
|
||
Stock = 10,
|
||
SurplusStock = 8,
|
||
Price = 100,
|
||
ScMoney = 50,
|
||
ShangId = 10,
|
||
GoodsListId = 0,
|
||
ImgUrl = "prize.jpg",
|
||
Sort = 1
|
||
};
|
||
await dbContext.GoodsItems.AddAsync(goodsItem);
|
||
await dbContext.SaveChangesAsync();
|
||
|
||
// Act
|
||
var result = await service.GetGoodsDetailAsync(1, 1, 0);
|
||
|
||
// Assert
|
||
Assert.NotNull(result);
|
||
Assert.NotNull(result.Goods);
|
||
Assert.Equal(1, result.Goods.Id);
|
||
Assert.Equal("测试商品", result.Goods.Title);
|
||
Assert.Equal(2, result.Goods.Type);
|
||
Assert.NotNull(result.LockInfo);
|
||
Assert.NotNull(result.GoodsList);
|
||
Assert.NotNull(result.LimitInfo);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 测试商品详情查询 - 自动选择箱号
|
||
/// Requirements: 2.2
|
||
/// </summary>
|
||
[Fact]
|
||
public async Task GetGoodsDetail_AutoSelectsBoxNumber_WhenGoodsNumIsZero()
|
||
{
|
||
// Arrange
|
||
var dbContext = CreateInMemoryDbContext();
|
||
var service = CreateGoodsService(dbContext);
|
||
|
||
await dbContext.GoodsTypes.AddAsync(new GoodsType { Value = 2, Name = "无限赏", FlName = "无限赏", CornerText = "无限赏" });
|
||
await dbContext.SaveChangesAsync();
|
||
|
||
var goods = new Good
|
||
{
|
||
Id = 1,
|
||
Title = "测试商品",
|
||
Type = 2,
|
||
Status = 1,
|
||
ShowIs = 0,
|
||
Price = 10,
|
||
Stock = 3,
|
||
ImgUrl = "img.jpg",
|
||
ImgUrlDetail = "detail.jpg"
|
||
};
|
||
await dbContext.Goods.AddAsync(goods);
|
||
|
||
// 添加奖品 - 箱号1无库存,箱号2有库存
|
||
var goodsItems = new List<GoodsItem>
|
||
{
|
||
new() { Id = 1, GoodsId = 1, Num = 1, Title = "奖品1", Stock = 10, SurplusStock = 0, ShangId = 10, GoodsListId = 0, ImgUrl = "p1.jpg" },
|
||
new() { Id = 2, GoodsId = 1, Num = 2, Title = "奖品2", Stock = 10, SurplusStock = 5, ShangId = 10, GoodsListId = 0, ImgUrl = "p2.jpg" }
|
||
};
|
||
await dbContext.GoodsItems.AddRangeAsync(goodsItems);
|
||
await dbContext.PrizeLevels.AddAsync(new PrizeLevel { Id = 10, Title = "A赏" });
|
||
await dbContext.SaveChangesAsync();
|
||
|
||
// Act - goodsNum=0 应自动选择有库存的箱号
|
||
var result = await service.GetGoodsDetailAsync(1, 0, 0);
|
||
|
||
// Assert - 应选择箱号2(有库存)
|
||
Assert.Equal(2, result.Goods.Num);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 测试商品详情查询 - 概率计算
|
||
/// Requirements: 2.3
|
||
/// </summary>
|
||
[Fact]
|
||
public async Task GetGoodsDetail_CalculatesProbabilityCorrectly()
|
||
{
|
||
// Arrange
|
||
var dbContext = CreateInMemoryDbContext();
|
||
var service = CreateGoodsService(dbContext);
|
||
|
||
await dbContext.GoodsTypes.AddAsync(new GoodsType { Value = 2, Name = "无限赏", FlName = "无限赏", CornerText = "无限赏" });
|
||
await dbContext.SaveChangesAsync();
|
||
|
||
var goods = new Good
|
||
{
|
||
Id = 1,
|
||
Title = "测试商品",
|
||
Type = 2,
|
||
Status = 1,
|
||
ShowIs = 0,
|
||
Price = 10,
|
||
Stock = 1,
|
||
ImgUrl = "img.jpg",
|
||
ImgUrlDetail = "detail.jpg"
|
||
};
|
||
await dbContext.Goods.AddAsync(goods);
|
||
|
||
// 添加奖品等级
|
||
await dbContext.PrizeLevels.AddAsync(new PrizeLevel { Id = 10, Title = "A赏" });
|
||
await dbContext.PrizeLevels.AddAsync(new PrizeLevel { Id = 11, Title = "B赏" });
|
||
await dbContext.SaveChangesAsync();
|
||
|
||
// 添加奖品 - 总剩余库存=10, A赏剩余2, B赏剩余8
|
||
var goodsItems = new List<GoodsItem>
|
||
{
|
||
new() { Id = 1, GoodsId = 1, Num = 1, Title = "A赏奖品", Stock = 5, SurplusStock = 2, ShangId = 10, GoodsListId = 0, ImgUrl = "a.jpg", Sort = 2 },
|
||
new() { Id = 2, GoodsId = 1, Num = 1, Title = "B赏奖品", Stock = 10, SurplusStock = 8, ShangId = 11, GoodsListId = 0, ImgUrl = "b.jpg", Sort = 1 }
|
||
};
|
||
await dbContext.GoodsItems.AddRangeAsync(goodsItems);
|
||
await dbContext.SaveChangesAsync();
|
||
|
||
// Act
|
||
var result = await service.GetGoodsDetailAsync(1, 1, 0);
|
||
|
||
// Assert - 概率计算: A赏=2/10*100=20%, B赏=8/10*100=80%
|
||
Assert.Equal(2, result.GoodsList.Count);
|
||
var aItem = result.GoodsList.First(x => x.ShangId == 10);
|
||
var bItem = result.GoodsList.First(x => x.ShangId == 11);
|
||
Assert.Contains("20", aItem.Pro);
|
||
Assert.Contains("80", bItem.Pro);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 测试商品详情查询 - 锁箱信息
|
||
/// Requirements: 2.4
|
||
/// </summary>
|
||
[Fact]
|
||
public async Task GetGoodsDetail_ReturnsLockInfo()
|
||
{
|
||
// Arrange
|
||
var dbContext = CreateInMemoryDbContext();
|
||
var service = CreateGoodsService(dbContext);
|
||
|
||
await dbContext.GoodsTypes.AddAsync(new GoodsType { Value = 2, Name = "无限赏", FlName = "无限赏", CornerText = "无限赏" });
|
||
await dbContext.SaveChangesAsync();
|
||
|
||
var goods = new Good
|
||
{
|
||
Id = 1,
|
||
Title = "测试商品",
|
||
Type = 2,
|
||
Status = 1,
|
||
ShowIs = 0,
|
||
Price = 10,
|
||
Stock = 1,
|
||
LockIs = 1, // 支持锁箱
|
||
ImgUrl = "img.jpg",
|
||
ImgUrlDetail = "detail.jpg"
|
||
};
|
||
await dbContext.Goods.AddAsync(goods);
|
||
|
||
// 添加锁箱记录
|
||
var futureTime = DateTimeOffset.UtcNow.AddMinutes(30).ToUnixTimeSeconds();
|
||
var goodsLock = new GoodsLock
|
||
{
|
||
Id = 1,
|
||
GoodsIdNum = "1_1",
|
||
UserId = 100,
|
||
EndTime = futureTime
|
||
};
|
||
await dbContext.GoodsLocks.AddAsync(goodsLock);
|
||
|
||
// 添加锁箱用户
|
||
var user = new User
|
||
{
|
||
Id = 100,
|
||
OpenId = "test_openid_100",
|
||
Uid = "test_uid_100",
|
||
Nickname = "锁箱用户",
|
||
HeadImg = "avatar.jpg"
|
||
};
|
||
await dbContext.Users.AddAsync(user);
|
||
await dbContext.SaveChangesAsync();
|
||
|
||
// Act
|
||
var result = await service.GetGoodsDetailAsync(1, 1, 0);
|
||
|
||
// Assert
|
||
Assert.NotNull(result.LockInfo);
|
||
Assert.Equal(1, result.LockInfo.LockIs);
|
||
Assert.Equal("锁箱用户", result.LockInfo.GoodsLockUserNickname);
|
||
Assert.True(result.LockInfo.GoodsLockSurplusTime > 0);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 测试商品详情查询 - 收藏状态
|
||
/// Requirements: 2.6
|
||
/// </summary>
|
||
[Fact]
|
||
public async Task GetGoodsDetail_ReturnsCollectionStatus()
|
||
{
|
||
// Arrange
|
||
var dbContext = CreateInMemoryDbContext();
|
||
var service = CreateGoodsService(dbContext);
|
||
|
||
await dbContext.GoodsTypes.AddAsync(new GoodsType { Value = 2, Name = "无限赏", FlName = "无限赏", CornerText = "无限赏" });
|
||
await dbContext.SaveChangesAsync();
|
||
|
||
var goods = new Good
|
||
{
|
||
Id = 1,
|
||
Title = "测试商品",
|
||
Type = 2,
|
||
Status = 1,
|
||
ShowIs = 0,
|
||
Price = 10,
|
||
Stock = 1,
|
||
ImgUrl = "img.jpg",
|
||
ImgUrlDetail = "detail.jpg"
|
||
};
|
||
await dbContext.Goods.AddAsync(goods);
|
||
|
||
// 添加收藏记录
|
||
var collection = new GoodsCollection
|
||
{
|
||
Id = 1,
|
||
UserId = 100,
|
||
GoodsId = 1,
|
||
Num = 1,
|
||
Type = 2
|
||
};
|
||
await dbContext.GoodsCollections.AddAsync(collection);
|
||
await dbContext.SaveChangesAsync();
|
||
|
||
// Act - 已收藏用户
|
||
var result = await service.GetGoodsDetailAsync(1, 1, 100);
|
||
|
||
// Assert
|
||
Assert.Equal(1, result.Goods.CollectionIs);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 测试商品详情查询 - 限购信息
|
||
/// Requirements: 2.7
|
||
/// </summary>
|
||
[Fact]
|
||
public async Task GetGoodsDetail_ReturnsLimitInfo()
|
||
{
|
||
// Arrange
|
||
var dbContext = CreateInMemoryDbContext();
|
||
var service = CreateGoodsService(dbContext);
|
||
|
||
await dbContext.GoodsTypes.AddAsync(new GoodsType { Value = 2, Name = "无限赏", FlName = "无限赏", CornerText = "无限赏" });
|
||
await dbContext.SaveChangesAsync();
|
||
|
||
var goods = new Good
|
||
{
|
||
Id = 1,
|
||
Title = "测试商品",
|
||
Type = 2,
|
||
Status = 1,
|
||
ShowIs = 0,
|
||
Price = 10,
|
||
Stock = 1,
|
||
DailyXiangou = 5,
|
||
QuanjuXiangou = 10,
|
||
ImgUrl = "img.jpg",
|
||
ImgUrlDetail = "detail.jpg"
|
||
};
|
||
await dbContext.Goods.AddAsync(goods);
|
||
await dbContext.SaveChangesAsync();
|
||
|
||
// Act
|
||
var result = await service.GetGoodsDetailAsync(1, 1, 0);
|
||
|
||
// Assert
|
||
Assert.NotNull(result.LimitInfo);
|
||
Assert.Equal(5, result.LimitInfo.DailyXiangou);
|
||
Assert.Equal(10, result.LimitInfo.QuanjuXiangou);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 测试商品详情查询 - 商品不存在
|
||
/// Requirements: 2.1
|
||
/// </summary>
|
||
[Fact]
|
||
public async Task GetGoodsDetail_ThrowsException_WhenGoodsNotFound()
|
||
{
|
||
// Arrange
|
||
var dbContext = CreateInMemoryDbContext();
|
||
var service = CreateGoodsService(dbContext);
|
||
|
||
// Act & Assert
|
||
await Assert.ThrowsAsync<InvalidOperationException>(
|
||
() => service.GetGoodsDetailAsync(999, 1, 0));
|
||
}
|
||
|
||
/// <summary>
|
||
/// 测试商品详情查询 - 商品已下架
|
||
/// Requirements: 2.1
|
||
/// </summary>
|
||
[Fact]
|
||
public async Task GetGoodsDetail_ThrowsException_WhenGoodsOffline()
|
||
{
|
||
// Arrange
|
||
var dbContext = CreateInMemoryDbContext();
|
||
var service = CreateGoodsService(dbContext);
|
||
|
||
var goods = new Good
|
||
{
|
||
Id = 1,
|
||
Title = "下架商品",
|
||
Type = 2,
|
||
Status = 0, // 下架
|
||
ShowIs = 0,
|
||
Price = 10,
|
||
Stock = 1,
|
||
ImgUrl = "img.jpg",
|
||
ImgUrlDetail = "detail.jpg"
|
||
};
|
||
await dbContext.Goods.AddAsync(goods);
|
||
await dbContext.SaveChangesAsync();
|
||
|
||
// Act & Assert
|
||
await Assert.ThrowsAsync<InvalidOperationException>(
|
||
() => service.GetGoodsDetailAsync(1, 1, 0));
|
||
}
|
||
|
||
#endregion
|
||
}
|