using BuildFlow.Application.Integration; using BuildFlow.Application.RagQA.Commands; using BuildFlow.Application.RagQA.DTOs; using BuildFlow.Domain.Entities.KnowledgeBase; using BuildFlow.Domain.Enums; using BuildFlow.Infrastructure.Persistence; using FluentAssertions; using Microsoft.EntityFrameworkCore; using MediatR; using Moq; using Workflow.Application.Integration.Commands; using Workflow.Application.Integration.DTOs; using Xunit; namespace BuildFlow.Rag.Tests; /// /// AI Bot 问答处理器测试(IM @AI → RAG/Workflow 串联)。 /// 用 Mock<IMediator> 模拟 RAG 查询与工作流触发,覆盖:无知识库、工作流意图触发、RAG 路径返回答案。 /// public class AiBotHandlerTests { [Fact] public async Task AnswerAsync_NoKnowledgeBase_ReturnsWarning() { await using var db = CreateDb(); var mediator = new Mock(); var handler = new AiBotHandler(mediator.Object, db); var answer = await handler.AnswerAsync("知识库里有什么", Guid.NewGuid(), Guid.NewGuid(), CancellationToken.None); answer.Should().Contain("暂无可用知识库"); mediator.Verify(m => m.Send(It.IsAny(), It.IsAny()), Times.Never); } [Fact] public async Task AnswerAsync_WorkflowIntentDetected_TriggersWorkflow() { await using var db = CreateDb(); var instanceId = Guid.NewGuid(); var mediator = new Mock(); mediator.Setup(m => m.Send(It.IsAny(), It.IsAny())) .ReturnsAsync(new WorkflowTriggerResultDto(true, instanceId, "报销流程", null)); var handler = new AiBotHandler(mediator.Object, db); var answer = await handler.AnswerAsync("帮我发起报销流程", Guid.NewGuid(), Guid.NewGuid(), CancellationToken.None); answer.Should().Contain("已为您发起"); answer.Should().Contain(instanceId.ToString()); mediator.Verify(m => m.Send( It.Is(c => c.DefinitionKey == "报销"), It.IsAny()), Times.Once); } [Fact] public async Task AnswerAsync_RagPath_ReturnsAnswer() { await using var db = CreateDb(); var kbId = Guid.NewGuid(); db.KnowledgeBases.Add(new KnowledgeBaseEntity { Id = kbId, Name = "测试知识库", Status = KnowledgeBaseStatusEnum.Active, CreatedBy = "test", UpdatedBy = "test", OperatorIP = "127.0.0.1", }); await db.SaveChangesAsync(); var mediator = new Mock(); mediator.Setup(m => m.Send(It.IsAny(), It.IsAny())) .ReturnsAsync(new RAGQueryResponse("这是知识库答案", [])); var handler = new AiBotHandler(mediator.Object, db); var answer = await handler.AnswerAsync("知识库里有什么", Guid.NewGuid(), Guid.NewGuid(), CancellationToken.None); answer.Should().Be("这是知识库答案"); mediator.Verify(m => m.Send( It.Is(c => c.KnowledgeBaseId == kbId), It.IsAny()), Times.Once); } private static RagDbContext CreateDb() { var options = new DbContextOptionsBuilder() .UseInMemoryDatabase($"rag-aibot-{Guid.NewGuid():N}") .Options; var db = new RagDbContext(options); db.SavingChanges += (_, _) => RagTestDb.FillAudit(db); return db; } }