using BuildFlow.Application.KnowledgeBase.Commands; using BuildFlow.Application.KnowledgeBase.Handlers; using BuildFlow.Application.KnowledgeBase.Queries; using BuildFlow.Domain.Enums; using BuildFlow.Infrastructure.Persistence; using BuildFlow.Rag.Tests.Stub; using BuildFlow.Shared.Domain.Exceptions; using BuildFlow.Shared.Infrastructure; using FluentAssertions; using Microsoft.EntityFrameworkCore; using Xunit; namespace BuildFlow.Rag.Tests; /// /// [SOP-RAG] 知识库 CRUD + 列表查询 Handler 全覆盖。 /// 飞书矩阵: rag/KnowledgeBase 子域(Create/Update/Delete/GetList 缺口→全补) /// public class KnowledgeBaseCrudTests { private static RagDbContext CreateDb([System.Runtime.CompilerServices.CallerMemberName] string name = "") { var userContext = new TestCurrentUserContext(); var options = new DbContextOptionsBuilder() .UseInMemoryDatabase($"rag-kb-{name}-{Guid.NewGuid():N}") .AddInterceptors(new AuditInterceptor(userContext)) .Options; return new RagDbContext(options); } [Fact] public async Task Create_Valid_ReturnsDtoWithDefaults() { var db = CreateDb(); var handler = new CreateKnowledgeBaseCommandHandler(db); var result = await handler.Handle( new CreateKnowledgeBaseCommand("我的知识库", "描述", null, null, null, null, null, null, null, null, null, null, null), CancellationToken.None); result.Name.Should().Be("我的知识库"); result.ChunkSize.Should().Be(500, "默认值"); result.RetrievalMode.Should().Be((int)RetrievalMode.Hybrid); result.VectorWeight.Should().Be(0.7); (await db.KnowledgeBases.CountAsync()).Should().Be(1); } [Fact] public async Task Create_EmptyName_ThrowsBusiness() { var db = CreateDb(); var handler = new CreateKnowledgeBaseCommandHandler(db); var act = async () => await handler.Handle( new CreateKnowledgeBaseCommand(" ", null, null, null, null, null, null, null, null, null, null, null, null), CancellationToken.None); await act.Should().ThrowAsync("空名称应拒绝"); } [Fact] public async Task Update_Existing_OverwritesFields() { var db = CreateDb(); var createHandler = new CreateKnowledgeBaseCommandHandler(db); var created = await createHandler.Handle( new CreateKnowledgeBaseCommand("原名", null, null, null, null, null, null, null, null, null, null, null, null), CancellationToken.None); var updateHandler = new UpdateKnowledgeBaseCommandHandler(db); var result = await updateHandler.Handle( new UpdateKnowledgeBaseCommand(created.Id, "新名", "新描述", 800, 100, null, null, null, null, null, null, 0.8, 0.9), CancellationToken.None); result.Name.Should().Be("新名"); result.ChunkSize.Should().Be(800); result.VectorWeight.Should().Be(0.9); } [Fact] public async Task Update_NonExistent_ThrowsNotFound() { var db = CreateDb(); var handler = new UpdateKnowledgeBaseCommandHandler(db); var act = async () => await handler.Handle( new UpdateKnowledgeBaseCommand(Guid.NewGuid(), "x", null, null, null, null, null, null, null, null, null, null, null), CancellationToken.None); await act.Should().ThrowAsync(); } [Fact] public async Task Delete_Existing_RemovesSoftly() { var db = CreateDb(); var createHandler = new CreateKnowledgeBaseCommandHandler(db); var created = await createHandler.Handle( new CreateKnowledgeBaseCommand("待删", null, null, null, null, null, null, null, null, null, null, null, null), CancellationToken.None); var deleteHandler = new DeleteKnowledgeBaseCommandHandler(db); await deleteHandler.Handle(new DeleteKnowledgeBaseCommand(created.Id), CancellationToken.None); (await db.KnowledgeBases.AnyAsync(k => k.Id == created.Id)).Should().BeFalse("软删后不可见"); } [Fact] public async Task GetList_ReturnsAllActive() { var db = CreateDb(); var createHandler = new CreateKnowledgeBaseCommandHandler(db); await createHandler.Handle(new CreateKnowledgeBaseCommand("KB1", null, null, null, null, null, null, null, null, null, null, null, null), CancellationToken.None); await createHandler.Handle(new CreateKnowledgeBaseCommand("KB2", null, null, null, null, null, null, null, null, null, null, null, null), CancellationToken.None); var queryHandler = new GetKnowledgeBasesQueryHandler(db); var result = await queryHandler.Handle(new GetKnowledgeBasesQuery(), CancellationToken.None); result.Should().HaveCount(2); } }