453 lines
14 KiB
C#
453 lines
14 KiB
C#
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;
|
|
|
|
/// <summary>
|
|
/// 收藏服务集成测试
|
|
/// 测试收藏/取消收藏流程
|
|
/// Requirements: 6.1-6.4
|
|
/// </summary>
|
|
public class CollectionServiceIntegrationTests
|
|
{
|
|
private HoneyBoxDbContext CreateInMemoryDbContext()
|
|
{
|
|
var options = new DbContextOptionsBuilder<HoneyBoxDbContext>()
|
|
.UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString())
|
|
.Options;
|
|
|
|
return new HoneyBoxDbContext(options);
|
|
}
|
|
|
|
private CollectionService CreateCollectionService(HoneyBoxDbContext dbContext)
|
|
{
|
|
var mockLogger = new Mock<ILogger<CollectionService>>();
|
|
var mockRedisService = new Mock<IRedisService>();
|
|
mockRedisService.Setup(x => x.DeleteAsync(It.IsAny<string>())).Returns(Task.CompletedTask);
|
|
return new CollectionService(dbContext, mockLogger.Object, mockRedisService.Object);
|
|
}
|
|
|
|
#region 收藏功能测试 (Requirements 6.1-6.4)
|
|
|
|
/// <summary>
|
|
/// 测试添加收藏
|
|
/// Requirements: 6.1
|
|
/// </summary>
|
|
[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);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 测试取消收藏
|
|
/// Requirements: 6.2
|
|
/// </summary>
|
|
[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);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 测试收藏往返一致性 - 添加后再取消
|
|
/// Requirements: 6.1, 6.2
|
|
/// </summary>
|
|
[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);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 测试收藏列表查询
|
|
/// Requirements: 6.4
|
|
/// </summary>
|
|
[Fact]
|
|
public async Task GetCollectionList_ReturnsUserCollections()
|
|
{
|
|
// Arrange
|
|
var dbContext = CreateInMemoryDbContext();
|
|
var service = CreateCollectionService(dbContext);
|
|
|
|
// 添加商品
|
|
var goods = new List<Good>
|
|
{
|
|
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<GoodsCollection>
|
|
{
|
|
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);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 测试收藏列表查询 - 按类型过滤
|
|
/// Requirements: 6.4
|
|
/// </summary>
|
|
[Fact]
|
|
public async Task GetCollectionList_FiltersByType()
|
|
{
|
|
// Arrange
|
|
var dbContext = CreateInMemoryDbContext();
|
|
var service = CreateCollectionService(dbContext);
|
|
|
|
// 添加商品
|
|
var goods = new List<Good>
|
|
{
|
|
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<GoodsCollection>
|
|
{
|
|
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);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 测试收藏列表查询 - 分页
|
|
/// Requirements: 6.4
|
|
/// </summary>
|
|
[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);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 测试检查收藏状态
|
|
/// Requirements: 6.1
|
|
/// </summary>
|
|
[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);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 测试删除收藏
|
|
/// Requirements: 6.2
|
|
/// </summary>
|
|
[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);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 测试删除不存在的收藏
|
|
/// Requirements: 6.2
|
|
/// </summary>
|
|
[Fact]
|
|
public async Task DeleteCollection_ThrowsException_WhenNotFound()
|
|
{
|
|
// Arrange
|
|
var dbContext = CreateInMemoryDbContext();
|
|
var service = CreateCollectionService(dbContext);
|
|
|
|
// Act & Assert
|
|
await Assert.ThrowsAsync<InvalidOperationException>(
|
|
() => service.DeleteCollectionAsync(100, 999));
|
|
}
|
|
|
|
/// <summary>
|
|
/// 测试收藏商品不存在
|
|
/// Requirements: 6.1
|
|
/// </summary>
|
|
[Fact]
|
|
public async Task ToggleCollection_ThrowsException_WhenGoodsNotFound()
|
|
{
|
|
// Arrange
|
|
var dbContext = CreateInMemoryDbContext();
|
|
var service = CreateCollectionService(dbContext);
|
|
|
|
// Act & Assert
|
|
await Assert.ThrowsAsync<InvalidOperationException>(
|
|
() => service.ToggleCollectionAsync(100, 999, 1));
|
|
}
|
|
|
|
/// <summary>
|
|
/// 测试收藏已下架商品
|
|
/// Requirements: 6.1
|
|
/// </summary>
|
|
[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<InvalidOperationException>(
|
|
() => service.ToggleCollectionAsync(100, 1, 1));
|
|
}
|
|
|
|
/// <summary>
|
|
/// 测试用户隔离 - 只返回当前用户的收藏
|
|
/// Requirements: 6.4
|
|
/// </summary>
|
|
[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<GoodsCollection>
|
|
{
|
|
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
|
|
}
|