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;
}
}