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
}