using System.Runtime.CompilerServices;
using BuildFlow.Shared.Domain.Common;
using IM.Domain.Entities.Conversation;
using IM.Domain.Entities.ConversationParticipant;
using IM.Domain.Entities.Group;
using IM.Domain.Entities.GroupMember;
using IM.Domain.Enums;
using IM.Infrastructure.Persistence;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
namespace BuildFlow.IM.Tests;
///
/// IM 模块测试数据库工厂:每个用例独立 InMemory 库,并通过 SavingChanges 事件自动补齐
/// IAuditable / IHasOperatorIP 审计字段(InMemory 无 AuditInterceptor,须手动补值,否则非空审计字段为 null)。
///
internal static class IMTestDb
{
public static ImDbContext Create([CallerMemberName] string testName = "")
{
var services = new ServiceCollection();
services.AddDbContext(options =>
options.UseInMemoryDatabase($"im-{testName}-{Guid.NewGuid()}"));
var db = services.BuildServiceProvider().GetRequiredService();
db.SavingChanges += FillAuditFields;
return db;
}
private static void FillAuditFields(object? sender, EventArgs args)
{
if (sender is not ImDbContext db) return;
foreach (var entry in db.ChangeTracker.Entries())
{
if (entry.Entity is IAuditable auditable)
{
auditable.CreatedBy ??= "test";
auditable.UpdatedBy ??= "test";
if (auditable.CreatedAt == default) auditable.CreatedAt = DateTime.UtcNow;
if (auditable.UpdatedAt == default) auditable.UpdatedAt = DateTime.UtcNow;
}
if (entry.Entity is IHasOperatorIP operatorEntity)
operatorEntity.OperatorIP ??= "127.0.0.1";
}
}
///
/// 构造一个群聊会话:群主 + 指成员 + 同步会话参与者。审计字段由 SavingChanges 事件补齐。
/// 返回 (会话Id, 群组Id)。
///
public static async Task<(Guid ConversationId, Guid GroupId)> SeedGroupAsync(
ImDbContext db, string name, Guid ownerId, params Guid[] memberIds)
{
var conversation = new ConversationEntity { Type = ConversationTypeEnum.Group };
db.Conversations.Add(conversation);
await db.SaveChangesAsync();
var group = new GroupEntity
{
ConversationId = conversation.Id,
Name = name,
OwnerId = ownerId
};
db.Groups.Add(group);
await db.SaveChangesAsync();
var allUserIds = new List { ownerId };
allUserIds.AddRange(memberIds.Where(id => id != ownerId));
foreach (var userId in allUserIds)
{
db.GroupMembers.Add(new GroupMemberEntity
{
GroupId = group.Id,
UserId = userId,
Role = userId == ownerId ? GroupMemberRoleEnum.Owner : GroupMemberRoleEnum.Member,
JoinedAt = DateTime.UtcNow
});
db.ConversationParticipants.Add(new ConversationParticipantEntity
{
ConversationId = conversation.Id,
UserId = userId,
JoinedAt = DateTime.UtcNow
});
}
await db.SaveChangesAsync();
return (conversation.Id, group.Id);
}
}