using System.Text; using File.Application.Common; using File.Application.Features.Files.Handlers; using File.Application.Features.Files.Queries; using File.Infrastructure.Storage; using FluentAssertions; using Moq; using Xunit; namespace BuildFlow.File.Tests; /// /// 下载文件查询处理器单元测试。覆盖正常下载、空内容两个场景。 /// Mock IS3StorageService 隔离 S3 外部依赖。 /// public class DownloadFileQueryHandlerTests { /// 测试用 bucket 解析器,固定返回 "test-bucket"。 private static IBucketResolver BucketResolver() { var mock = new Mock(); mock.Setup(r => r.GetDefaultBucketAsync(It.IsAny())).ReturnsAsync("test-bucket"); return mock.Object; } /// 创建 Mock S3 + Handler。 private static (Mock s3Mock, DownloadFileQueryHandler handler) Setup(string content = "hello world") { var s3Mock = new Mock(); var stream = new MemoryStream(Encoding.UTF8.GetBytes(content)); s3Mock .Setup(x => x.DownloadFileAsync("test-bucket", "test-key", It.IsAny())) .ReturnsAsync((stream, "text/plain")); var handler = new DownloadFileQueryHandler(s3Mock.Object, BucketResolver()); return (s3Mock, handler); } [Fact] public async Task DownloadFile_WithValidPath_ReturnsContent() { // Arrange var (s3Mock, handler) = Setup("hello world"); // Act var result = await handler.Handle( new DownloadFileQuery("test-key"), CancellationToken.None); // Assert — 返回的是 S3 原始流,透传给调用方;ContentType 取 S3 返回的真实类型 result.Should().NotBeNull(); result.Stream.Should().NotBeNull(); result.ContentType.Should().Be("text/plain"); result.FileName.Should().Be("test-key"); s3Mock.Verify(x => x.DownloadFileAsync("test-bucket", "test-key", It.IsAny()), Times.Once); } [Fact] public async Task DownloadFile_S3ReturnsEmpty_ReturnsReadableEmptyStream() { // Arrange — DownloadFileQueryHandler 透传 S3 流,空内容对应空 MemoryStream var s3Mock = new Mock(); var emptyStream = new MemoryStream(); s3Mock .Setup(x => x.DownloadFileAsync(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync((emptyStream, "application/octet-stream")); var handler = new DownloadFileQueryHandler(s3Mock.Object, BucketResolver()); // Act var result = await handler.Handle( new DownloadFileQuery("test-key"), CancellationToken.None); // Assert — Handler 透传空流,长度为 0 result.Stream.Should().NotBeNull(); result.Stream.Length.Should().Be(0); } }