97 lines
3.6 KiB
C#
97 lines
3.6 KiB
C#
using BuildFlow.Application.Document.Commands;
|
|
using BuildFlow.Application.Document.Handlers;
|
|
using BuildFlow.Domain.Entities.KnowledgeBase;
|
|
using BuildFlow.Domain.Enums;
|
|
using BuildFlow.Infrastructure.Persistence;
|
|
using BuildFlow.Shared.Domain.Common;
|
|
using File.Application.Features.Files.Commands;
|
|
using File.Application.Features.Files.DTOs;
|
|
using MediatR;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.Extensions.Configuration;
|
|
using Moq;
|
|
using Xunit;
|
|
|
|
namespace BuildFlow.Rag.Tests;
|
|
|
|
/// <summary>
|
|
/// 文档上传处理器测试。文件内容必须通过 File Application 命令上传。
|
|
/// </summary>
|
|
public class UploadDocumentCommandHandlerTests
|
|
{
|
|
[Fact]
|
|
public async Task Handle_ShouldSendUploadFileCommandAndPersistDocument()
|
|
{
|
|
await using var db = CreateDb();
|
|
var knowledgeBaseId = Guid.NewGuid();
|
|
db.KnowledgeBases.Add(BuildKnowledgeBase(knowledgeBaseId));
|
|
await db.SaveChangesAsync();
|
|
await using var fileStream = new MemoryStream([1, 2, 3]);
|
|
var mediator = new Mock<IMediator>();
|
|
mediator.Setup(m => m.Send(It.IsAny<UploadFileCommand>(), It.IsAny<CancellationToken>()))
|
|
.ReturnsAsync((UploadFileCommand command, CancellationToken _) =>
|
|
new UploadFileResponse("uploaded", command.ObjectKey));
|
|
var config = new ConfigurationManager
|
|
{
|
|
["FileService:Bucket"] = "rag-documents"
|
|
};
|
|
var handler = new UploadDocumentCommandHandler(db, mediator.Object, config);
|
|
|
|
var result = await handler.Handle(new UploadDocumentCommand(
|
|
knowledgeBaseId,
|
|
"Architecture",
|
|
"architecture.md",
|
|
fileStream,
|
|
fileStream.Length,
|
|
"text/markdown"), CancellationToken.None);
|
|
|
|
var document = await db.Documents.SingleAsync(doc => doc.Id == result.Id);
|
|
Assert.StartsWith("rag-documents/docs/", document.FilePath);
|
|
mediator.Verify(m => m.Send(
|
|
It.Is<UploadFileCommand>(command =>
|
|
command.ObjectKey.StartsWith($"docs/{knowledgeBaseId}/", StringComparison.Ordinal)
|
|
&& command.ObjectKey.EndsWith("/architecture.md", StringComparison.Ordinal)
|
|
&& ReferenceEquals(command.Data, fileStream)
|
|
&& command.ContentType == "text/markdown"
|
|
&& command.Size == fileStream.Length),
|
|
It.IsAny<CancellationToken>()), Times.Once);
|
|
}
|
|
|
|
private static RagDbContext CreateDb()
|
|
{
|
|
var db = new RagDbContext(
|
|
new DbContextOptionsBuilder<RagDbContext>()
|
|
.UseInMemoryDatabase($"rag-upload-{Guid.NewGuid():N}")
|
|
.Options);
|
|
db.SavingChanges += (_, _) =>
|
|
{
|
|
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";
|
|
}
|
|
}
|
|
};
|
|
return db;
|
|
}
|
|
|
|
private static KnowledgeBaseEntity BuildKnowledgeBase(Guid id) => new()
|
|
{
|
|
Id = id,
|
|
Name = "Architecture",
|
|
Status = KnowledgeBaseStatusEnum.Active,
|
|
CreatedBy = "test",
|
|
UpdatedBy = "test",
|
|
OperatorIP = "127.0.0.1",
|
|
};
|
|
}
|