using HoneyBox.Core.Interfaces; using HoneyBox.Core.Services; using HoneyBox.Model.Data; using HoneyBox.Model.Entities; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Moq; using Xunit; namespace HoneyBox.Tests.Integration; /// /// 收藏服务集成测试 /// 测试收藏/取消收藏流程 /// Requirements: 6.1-6.4 /// public class CollectionServiceIntegrationTests { private HoneyBoxDbContext CreateInMemoryDbContext() { var options = new DbContextOptionsBuilder() .UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString()) .Options; return new HoneyBoxDbContext(options); } private CollectionService CreateCollectionService(HoneyBoxDbContext dbContext) { var mockLogger = new Mock>(); var mockRedisService = new Mock(); mockRedisService.Setup(x => x.DeleteAsync(It.IsAny())).Returns(Task.CompletedTask); return new CollectionService(dbContext, mockLogger.Object, mockRedisService.Object); } #region 收藏功能测试 (Requirements 6.1-6.4) /// /// 测试添加收藏 /// Requirements: 6.1 /// [Fact] public async Task ToggleCollection_AddsCollection_WhenNotCollected() { // Arrange var dbContext = CreateInMemoryDbContext(); var service = CreateCollectionService(dbContext); var goods = new Good { Id = 1, Title = "测试商品", Type = 2, Status = 1, ShowIs = 0, Price = 10, Stock = 5, ImgUrl = "img.jpg", ImgUrlDetail = "detail.jpg" }; await dbContext.Goods.AddAsync(goods); await dbContext.SaveChangesAsync(); // Act var result = await service.ToggleCollectionAsync(100, 1, 1); // Assert Assert.True(result); var collection = await dbContext.GoodsCollections .FirstOrDefaultAsync(c => c.UserId == 100 && c.GoodsId == 1 && c.Num == 1); Assert.NotNull(collection); } /// /// 测试取消收藏 /// Requirements: 6.2 /// [Fact] public async Task ToggleCollection_RemovesCollection_WhenAlreadyCollected() { // Arrange var dbContext = CreateInMemoryDbContext(); var service = CreateCollectionService(dbContext); var goods = new Good { Id = 1, Title = "测试商品", Type = 2, Status = 1, ShowIs = 0, Price = 10, Stock = 5, 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, CreatedAt = DateTime.Now }; await dbContext.GoodsCollections.AddAsync(collection); await dbContext.SaveChangesAsync(); // Act - 再次调用应取消收藏 var result = await service.ToggleCollectionAsync(100, 1, 1); // Assert Assert.True(result); var exists = await dbContext.GoodsCollections .AnyAsync(c => c.UserId == 100 && c.GoodsId == 1 && c.Num == 1); Assert.False(exists); } /// /// 测试收藏往返一致性 - 添加后再取消 /// Requirements: 6.1, 6.2 /// [Fact] public async Task ToggleCollection_RoundTrip_AddsAndRemoves() { // Arrange var dbContext = CreateInMemoryDbContext(); var service = CreateCollectionService(dbContext); var goods = new Good { Id = 1, Title = "测试商品", Type = 2, Status = 1, ShowIs = 0, Price = 10, Stock = 5, ImgUrl = "img.jpg", ImgUrlDetail = "detail.jpg" }; await dbContext.Goods.AddAsync(goods); await dbContext.SaveChangesAsync(); // Act - 第一次调用:添加收藏 await service.ToggleCollectionAsync(100, 1, 1); var afterAdd = await service.IsCollectedAsync(100, 1, 1); // Act - 第二次调用:取消收藏 await service.ToggleCollectionAsync(100, 1, 1); var afterRemove = await service.IsCollectedAsync(100, 1, 1); // Assert Assert.True(afterAdd); Assert.False(afterRemove); } /// /// 测试收藏列表查询 /// Requirements: 6.4 /// [Fact] public async Task GetCollectionList_ReturnsUserCollections() { // Arrange var dbContext = CreateInMemoryDbContext(); var service = CreateCollectionService(dbContext); // 添加商品 var goods = new List { new() { Id = 1, Title = "商品1", Type = 2, Status = 1, ShowIs = 0, Price = 10, Stock = 5, ImgUrl = "img1.jpg", ImgUrlDetail = "detail1.jpg" }, new() { Id = 2, Title = "商品2", Type = 2, Status = 1, ShowIs = 0, Price = 20, Stock = 10, ImgUrl = "img2.jpg", ImgUrlDetail = "detail2.jpg" } }; await dbContext.Goods.AddRangeAsync(goods); // 添加收藏 var collections = new List { new() { Id = 1, UserId = 100, GoodsId = 1, Num = 1, Type = 2, CreatedAt = DateTime.Now }, new() { Id = 2, UserId = 100, GoodsId = 2, Num = 1, Type = 2, CreatedAt = DateTime.Now } }; await dbContext.GoodsCollections.AddRangeAsync(collections); await dbContext.SaveChangesAsync(); // Act var result = await service.GetCollectionListAsync(100, 0, 1, 10); // Assert Assert.NotNull(result); Assert.Equal(2, result.Data.Count); } /// /// 测试收藏列表查询 - 按类型过滤 /// Requirements: 6.4 /// [Fact] public async Task GetCollectionList_FiltersByType() { // Arrange var dbContext = CreateInMemoryDbContext(); var service = CreateCollectionService(dbContext); // 添加商品 var goods = new List { new() { Id = 1, Title = "商品1", Type = 2, Status = 1, ShowIs = 0, Price = 10, Stock = 5, ImgUrl = "img1.jpg", ImgUrlDetail = "detail1.jpg" }, new() { Id = 2, Title = "商品2", Type = 6, Status = 1, ShowIs = 0, Price = 20, Stock = 10, ImgUrl = "img2.jpg", ImgUrlDetail = "detail2.jpg" } }; await dbContext.Goods.AddRangeAsync(goods); // 添加收藏 var collections = new List { new() { Id = 1, UserId = 100, GoodsId = 1, Num = 1, Type = 2, CreatedAt = DateTime.Now }, new() { Id = 2, UserId = 100, GoodsId = 2, Num = 1, Type = 6, CreatedAt = DateTime.Now } }; await dbContext.GoodsCollections.AddRangeAsync(collections); await dbContext.SaveChangesAsync(); // Act - 只查询类型2的收藏 var result = await service.GetCollectionListAsync(100, 2, 1, 10); // Assert Assert.Single(result.Data); Assert.Equal(2, result.Data[0].Type); } /// /// 测试收藏列表查询 - 分页 /// Requirements: 6.4 /// [Fact] public async Task GetCollectionList_PaginationWorksCorrectly() { // Arrange var dbContext = CreateInMemoryDbContext(); var service = CreateCollectionService(dbContext); // 添加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, ImgUrl = $"img{i}.jpg", ImgUrlDetail = $"detail{i}.jpg" }).ToList(); await dbContext.Goods.AddRangeAsync(goods); var collections = Enumerable.Range(1, 15).Select(i => new GoodsCollection { Id = i, UserId = 100, GoodsId = i, Num = 1, Type = 2, CreatedAt = DateTime.Now.AddMinutes(-i) }).ToList(); await dbContext.GoodsCollections.AddRangeAsync(collections); await dbContext.SaveChangesAsync(); // Act var page1 = await service.GetCollectionListAsync(100, 0, 1, 10); var page2 = await service.GetCollectionListAsync(100, 0, 2, 10); // Assert Assert.Equal(2, page1.LastPage); Assert.Equal(10, page1.Data.Count); Assert.Equal(5, page2.Data.Count); } /// /// 测试检查收藏状态 /// Requirements: 6.1 /// [Fact] public async Task IsCollected_ReturnsCorrectStatus() { // Arrange var dbContext = CreateInMemoryDbContext(); var service = CreateCollectionService(dbContext); var collection = new GoodsCollection { Id = 1, UserId = 100, GoodsId = 1, Num = 1, Type = 2, CreatedAt = DateTime.Now }; await dbContext.GoodsCollections.AddAsync(collection); await dbContext.SaveChangesAsync(); // Act var isCollected = await service.IsCollectedAsync(100, 1, 1); var isNotCollected = await service.IsCollectedAsync(100, 2, 1); // Assert Assert.True(isCollected); Assert.False(isNotCollected); } /// /// 测试删除收藏 /// Requirements: 6.2 /// [Fact] public async Task DeleteCollection_RemovesCollectionById() { // Arrange var dbContext = CreateInMemoryDbContext(); var service = CreateCollectionService(dbContext); var collection = new GoodsCollection { Id = 1, UserId = 100, GoodsId = 1, Num = 1, Type = 2, CreatedAt = DateTime.Now }; await dbContext.GoodsCollections.AddAsync(collection); await dbContext.SaveChangesAsync(); // Act var result = await service.DeleteCollectionAsync(100, 1); // Assert Assert.True(result); var exists = await dbContext.GoodsCollections.AnyAsync(c => c.Id == 1); Assert.False(exists); } /// /// 测试删除不存在的收藏 /// Requirements: 6.2 /// [Fact] public async Task DeleteCollection_ThrowsException_WhenNotFound() { // Arrange var dbContext = CreateInMemoryDbContext(); var service = CreateCollectionService(dbContext); // Act & Assert await Assert.ThrowsAsync( () => service.DeleteCollectionAsync(100, 999)); } /// /// 测试收藏商品不存在 /// Requirements: 6.1 /// [Fact] public async Task ToggleCollection_ThrowsException_WhenGoodsNotFound() { // Arrange var dbContext = CreateInMemoryDbContext(); var service = CreateCollectionService(dbContext); // Act & Assert await Assert.ThrowsAsync( () => service.ToggleCollectionAsync(100, 999, 1)); } /// /// 测试收藏已下架商品 /// Requirements: 6.1 /// [Fact] public async Task ToggleCollection_ThrowsException_WhenGoodsOffline() { // Arrange var dbContext = CreateInMemoryDbContext(); var service = CreateCollectionService(dbContext); var goods = new Good { Id = 1, Title = "下架商品", Type = 2, Status = 0, // 下架 ShowIs = 0, Price = 10, Stock = 5, ImgUrl = "img.jpg", ImgUrlDetail = "detail.jpg" }; await dbContext.Goods.AddAsync(goods); await dbContext.SaveChangesAsync(); // Act & Assert await Assert.ThrowsAsync( () => service.ToggleCollectionAsync(100, 1, 1)); } /// /// 测试用户隔离 - 只返回当前用户的收藏 /// Requirements: 6.4 /// [Fact] public async Task GetCollectionList_OnlyReturnsCurrentUserCollections() { // Arrange var dbContext = CreateInMemoryDbContext(); var service = CreateCollectionService(dbContext); // 添加商品 var goods = new Good { Id = 1, Title = "商品1", Type = 2, Status = 1, ShowIs = 0, Price = 10, Stock = 5, ImgUrl = "img1.jpg", ImgUrlDetail = "detail1.jpg" }; await dbContext.Goods.AddAsync(goods); // 添加不同用户的收藏 var collections = new List { new() { Id = 1, UserId = 100, GoodsId = 1, Num = 1, Type = 2, CreatedAt = DateTime.Now }, new() { Id = 2, UserId = 200, GoodsId = 1, Num = 1, Type = 2, CreatedAt = DateTime.Now } }; await dbContext.GoodsCollections.AddRangeAsync(collections); await dbContext.SaveChangesAsync(); // Act var result = await service.GetCollectionListAsync(100, 0, 1, 10); // Assert Assert.Single(result.Data); Assert.Equal(1, result.Data[0].GoodsId); } #endregion }