- 移除AbortMultipartCommand中的BucketName参数 - 移除CompleteMultipartCommand中的BucketName参数 - 移除DeleteFileCommand中的BucketName参数 - 移除DownloadFileQuery中的BucketName参数 - 移除GetFileContentQuery中的BucketName参数 - 移除GetFilePreviewQuery中的BucketName参数 - 移除GetOfficePreviewQuery中的BucketName参数 - 移除InitMultipartCommand中的BucketName参数 - 在各处理器中注入IBucketResolver并获取默认桶 - 更新所有相关端点和请求模型移除bucket参数 - 修改测试代码适配参数变更 - 添加IM离线消息到平台通知中心的跨模块集成实现
80 lines
2.9 KiB
C#
80 lines
2.9 KiB
C#
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;
|
||
|
||
/// <summary>
|
||
/// 下载文件查询处理器单元测试。覆盖正常下载、空内容两个场景。
|
||
/// Mock IS3StorageService 隔离 S3 外部依赖。
|
||
/// </summary>
|
||
public class DownloadFileQueryHandlerTests
|
||
{
|
||
/// <summary>测试用 bucket 解析器,固定返回 "test-bucket"。</summary>
|
||
private static IBucketResolver BucketResolver()
|
||
{
|
||
var mock = new Mock<IBucketResolver>();
|
||
mock.Setup(r => r.GetDefaultBucketAsync(It.IsAny<CancellationToken>())).ReturnsAsync("test-bucket");
|
||
return mock.Object;
|
||
}
|
||
|
||
/// <summary>创建 Mock S3 + Handler。</summary>
|
||
private static (Mock<IS3StorageService> s3Mock, DownloadFileQueryHandler handler) Setup(string content = "hello world")
|
||
{
|
||
var s3Mock = new Mock<IS3StorageService>();
|
||
var stream = new MemoryStream(Encoding.UTF8.GetBytes(content));
|
||
s3Mock
|
||
.Setup(x => x.DownloadFileAsync("test-bucket", "test-key", It.IsAny<CancellationToken>()))
|
||
.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<CancellationToken>()), Times.Once);
|
||
}
|
||
|
||
[Fact]
|
||
public async Task DownloadFile_S3ReturnsEmpty_ReturnsReadableEmptyStream()
|
||
{
|
||
// Arrange — DownloadFileQueryHandler 透传 S3 流,空内容对应空 MemoryStream
|
||
var s3Mock = new Mock<IS3StorageService>();
|
||
var emptyStream = new MemoryStream();
|
||
s3Mock
|
||
.Setup(x => x.DownloadFileAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<CancellationToken>()))
|
||
.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);
|
||
}
|
||
}
|