You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Moq在C#中模拟Azure Storage Account并测试BlobService?

使用Moq为BlobService编写单元测试的最佳实践

核心思路

要测试BlobService的GetBlobAsync方法,关键是模拟其依赖的Azure Blob存储客户端(BlobContainerClient和BlobClient),避免依赖真实的云存储服务,确保测试快速且隔离。

步骤1:准备依赖包

确保测试项目安装以下NuGet包:

  • Moq:用于创建模拟对象
  • xunit(或NUnit/MSTest):测试框架
  • Azure.Storage.Blobs:提供Blob相关类型定义

步骤2:编写测试用例示例

以下是针对GetBlobAsync的完整测试实现,包含成功场景和异常场景:

using Moq;
using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Models;
using System.IO;
using System.Threading.Tasks;
using Xunit;

public class BlobServiceTests
{
    [Fact]
    public async Task GetBlobAsync_ValidName_ReturnsCorrectBlobInfo()
    {
        // 1. 准备测试数据
        string blobName = "test-file.txt";
        string contentType = "text/plain";
        var contentStream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes("Test content"));

        // 2. 模拟BlobDownloadResult
        var mockBlobDownloadResult = new BlobDownloadResult
        {
            Content = contentStream,
            Details = new BlobDownloadDetails { ContentType = contentType }
        };

        // 3. 模拟BlobClient
        var mockBlobClient = new Mock<BlobClient>();
        mockBlobClient.Setup(client => client.DownloadContentAsync(default))
                      .ReturnsAsync(mockBlobDownloadResult);

        // 4. 模拟BlobContainerClient
        var mockContainerClient = new Mock<BlobContainerClient>();
        mockContainerClient.Setup(container => container.GetBlobClient(blobName))
                          .Returns(mockBlobClient.Object);

        // 5. 实例化待测试的BlobService
        var blobService = new BlobService(mockContainerClient.Object); // 假设构造函数注入BlobContainerClient

        // 6. 执行测试方法
        var result = await blobService.GetBlobAsync(blobName);

        // 7. 断言结果符合预期
        Assert.NotNull(result);
        Assert.Equal(contentType, result.ContentType);
        
        // 验证流内容是否正确
        contentStream.Position = 0;
        var resultContent = new StreamReader(result.Content).ReadToEnd();
        Assert.Equal("Test content", resultContent);

        // 验证依赖方法是否被正确调用
        mockContainerClient.Verify(container => container.GetBlobClient(blobName), Times.Once);
        mockBlobClient.Verify(client => client.DownloadContentAsync(default), Times.Once);
    }

    [Fact]
    public async Task GetBlobAsync_BlobNotFound_ThrowsException()
    {
        // 1. 准备测试数据
        string blobName = "non-existent-file.txt";

        // 2. 模拟BlobClient抛出异常
        var mockBlobClient = new Mock<BlobClient>();
        mockBlobClient.Setup(client => client.DownloadContentAsync(default))
                      .ThrowsAsync(new Azure.RequestFailedException(404, "Blob not found"));

        // 3. 模拟BlobContainerClient
        var mockContainerClient = new Mock<BlobContainerClient>();
        mockContainerClient.Setup(container => container.GetBlobClient(blobName))
                          .Returns(mockBlobClient.Object);

        // 4. 实例化BlobService
        var blobService = new BlobService(mockContainerClient.Object);

        // 5. 断言抛出预期异常
        await Assert.ThrowsAsync<Azure.RequestFailedException>(() => blobService.GetBlobAsync(blobName));
    }
}

关键注意事项

  • 依赖注入:确保BlobService通过构造函数接收BlobContainerClient,这样才能在测试中替换为模拟对象。
  • 模拟异步方法:使用ReturnsAsync模拟异步方法的返回值,ThrowsAsync模拟异常。
  • 验证调用:使用Verify方法确认依赖的方法被调用了正确的次数,确保业务逻辑符合预期。
  • 处理流对象:测试流内容时,注意重置流的位置,避免读取空内容。

其他方法的测试思路

对于ListBlobsAsync、UploadFileBlobAsync等方法,核心思路一致:

  • 模拟BlobContainerClient对应的方法(如GetBlobsAsync、GetBlobClient)
  • 设置返回值或异常,验证业务逻辑的处理结果

内容的提问来源于stack exchange,提问作者Nabeel A.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 15:01:05