using AutoMapper; using IM_API.Domain.Events; using IM_API.Dtos.Friend; using IM_API.Exceptions; using IM_API.Models; using IM_API.Services; using MassTransit; // 必须引入 using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Moq; using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using Xunit; public class FriendServiceTests { private readonly Mock _mockEndpoint = new(); private readonly Mock> _mockLogger = new(); #region 辅助构造方法 private ImContext CreateDbContext() { var options = new DbContextOptionsBuilder() .UseInMemoryDatabase(Guid.NewGuid().ToString()) // 确保每个测试数据库隔离 .Options; return new ImContext(options); } private IMapper CreateMapper() { var config = new MapperConfiguration(cfg => { // 补充你业务中实际需要的映射规则 cfg.CreateMap(); cfg.CreateMap(); cfg.CreateMap() .ForMember(d => d.UserId, o => o.MapFrom(s => s.ResponseUser)) .ForMember(d => d.FriendId, o => o.MapFrom(s => s.RequestUser)); }); return config.CreateMapper(); } private FriendService CreateService(ImContext context) { // 注入 Mock 对象和真实的 Mapper/Context return new FriendService(context, _mockLogger.Object, CreateMapper(), _mockEndpoint.Object); } #endregion [Fact] public async Task SendFriendRequestAsync_Success_ShouldSaveAndPublish() { // Arrange var context = CreateDbContext(); context.Users.AddRange( new User { Id = 1, Username = "Sender", Password = "..." }, new User { Id = 2, Username = "Receiver", Password = "..." } ); await context.SaveChangesAsync(); var service = CreateService(context); var dto = new FriendRequestDto { ToUserId = 2, FromUserId = 2, Description = "Hello" , RemarkName = "测试备注" }; // Act //var result = await service.SendFriendRequestAsync(dto); // Assert //Assert.True(result); //Assert.Single(context.FriendRequests); // 验证事件是否发布到了 MQ /* _mockEndpoint.Verify(x => x.Publish( It.Is(e => e.FromUserId == 1 && e.ToUserId == 2), It.IsAny()), Times.Once); */ } [Fact] public async Task SendFriendRequestAsync_UserNotFound_ShouldThrow() { // Arrange var context = CreateDbContext(); var service = CreateService(context); var dto = new FriendRequestDto { ToUserId = 99 }; // 不存在的用户 // Act & Assert await Assert.ThrowsAsync(() => service.SendFriendRequestAsync(dto)); } [Fact] public async Task SendFriendRequestAsync_AlreadyExists_ShouldThrow() { // Arrange var context = CreateDbContext(); context.Users.Add(new User { Id = 2, Password = "123", Username = "111" }); context.FriendRequests.Add(new FriendRequest { RequestUser = 1, ResponseUser = 2, State = (sbyte)FriendRequestState.Pending, RemarkName = "测试备注" }); await context.SaveChangesAsync(); var service = CreateService(context); // Act & Assert await Assert.ThrowsAsync(() => service.SendFriendRequestAsync(new FriendRequestDto { ToUserId = 2 })); } [Fact] public async Task BlockFriendAsync_ValidId_ShouldUpdateStatus() { // Arrange var context = CreateDbContext(); var friend = new Friend { Id = 50, UserId = 1, FriendId = 2, StatusEnum = FriendStatus.Added,RemarkName = "测试备注" }; context.Friends.Add(friend); await context.SaveChangesAsync(); var service = CreateService(context); // Act await service.BlockeFriendAsync(50); // Assert var updated = await context.Friends.FindAsync(50); Assert.Equal(FriendStatus.Blocked, updated.StatusEnum); } [Fact] public async Task GetFriendListAsync_ShouldFilterByStatus() { // Arrange var context = CreateDbContext(); context.Friends.AddRange( new Friend { UserId = 1, FriendId = 2, StatusEnum = FriendStatus.Added,RemarkName = "111" }, new Friend { UserId = 1, FriendId = 3, StatusEnum = FriendStatus.Blocked,RemarkName = "222" } ); await context.SaveChangesAsync(); var service = CreateService(context); // Act var result = await service.GetFriendListAsync(1, 1, 10, false); // Assert //Assert.Single(result); // 只应该拿到 Added 状态的 } }