using File.Application.Features.Files.Commands; using File.Application.Features.Files.Handlers; using File.Application.Features.Files.Services; using File.Domain.Entities.FileMeta; using File.Infrastructure.Persistence; using File.Infrastructure.Storage; using FluentAssertions; using Microsoft.Extensions.Logging.Abstractions; using Moq; using Xunit; namespace BuildFlow.File.Tests; /// /// ProcessUnverifiedFileSizesCommandHandler 测试。该 Handler 仅将命令委托给 /// FileSizeVerificationProcessor,故覆盖:成功回填大小 + 委托层对越界参数的前置校验。 /// public class ProcessUnverifiedFileSizesCommandHandlerTests { private static FileSizeVerificationProcessor NewProcessor(FileDbContext db, Mock s3) => new(db, s3.Object, NullLogger.Instance); private static FileMetaEntity NewUnverifiedFile() => new() { Name = "f.bin", S3Key = Guid.NewGuid().ToString(), S3Bucket = "files", ContentType = "application/octet-stream", OwnerId = "user-001", Size = 0, SizeVerified = false, }; [Fact] public async Task Process_存在未确认文件_经S3回填大小并标记已确认() { await using var db = FileTestDb.Create(); var file = NewUnverifiedFile(); db.Files.Add(file); await db.SaveChangesAsync(); var s3 = new Mock(); s3.Setup(x => x.GetObjectSizeAsync(file.S3Bucket, file.S3Key, It.IsAny())) .ReturnsAsync(2048L); var handler = new ProcessUnverifiedFileSizesCommandHandler(NewProcessor(db, s3)); var processed = await handler.Handle(new ProcessUnverifiedFileSizesCommand(100, 4), CancellationToken.None); processed.Should().Be(1, "应处理 1 个未确认文件"); // file 为同一 DbContext 跟踪的实例,处理器 SaveChangesAsync 后属性已更新 file.Size.Should().Be(2048L); file.SizeVerified.Should().BeTrue("大小应被标记已确认"); } [Fact] public async Task Process_批量大小越界_委托处理器抛出参数范围异常() { await using var db = FileTestDb.Create(); var handler = new ProcessUnverifiedFileSizesCommandHandler(NewProcessor(db, new Mock())); var act = async () => await handler.Handle( new ProcessUnverifiedFileSizesCommand(0, 4), CancellationToken.None); // 越界校验在依赖(S3/DB)调用之前,可在 InMemory 直接覆盖。 await act.Should().ThrowAsync(); } }