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

如何Mock Azure CryptographyClient的EncryptAsync并返回有效EncryptResult?

解决Azure CryptographyClient.EncryptAsync的Mock问题及替代测试方案

一、修改Mock生成合法EncryptResult的方法

由于EncryptResult是不可变类(无公共setter),可以通过反射修改私有字段生成有效实例,具体步骤如下:

  1. 使用Activator.CreateInstance创建EncryptResult实例(绕过无公共构造的限制)
  2. 通过反射定位EncryptResult的私有字段(通常名为_ciphertext)并赋值
  3. 将该实例作为Mock方法的返回值

示例代码(结合Moq框架):

using System.Reflection;
using Azure.Security.KeyVault.Keys.Cryptography;
using Moq;

// 创建EncryptResult实例
var encryptResult = Activator.CreateInstance<EncryptResult>();

// 反射获取私有字段并设置模拟密文
var ciphertextField = typeof(EncryptResult).GetField(
    "_ciphertext", 
    BindingFlags.Instance | BindingFlags.NonPublic);
ciphertextField.SetValue(encryptResult, Convert.FromBase64String("aGVsbG8gd29ybGQ=")); // 模拟密文

// Mock CryptographyClient的EncryptAsync方法
var mockCryptoClient = new Mock<CryptographyClient>();
mockCryptoClient.Setup(c => c.EncryptAsync(
        It.IsAny<EncryptionAlgorithm>(), 
        It.IsAny<byte[]>(), 
        default))
    .ReturnsAsync(encryptResult);

注意:私有字段名称可能随Azure SDK版本变化,若出现找不到字段的情况,可通过调试查看EncryptResult的内部字段名调整。

二、其他测试方案

1. 引入抽象层解耦依赖

对CryptographyClient的加密能力进行抽象,定义自定义接口,让KeyVaultClientWrapper依赖该接口而非直接依赖Azure SDK类,测试时可自由Mock返回值。

示例代码:

// 自定义加密服务接口
public interface IKeyVaultCryptoService
{
    Task<IEncryptResult> EncryptAsync(
        EncryptionAlgorithm algorithm, 
        byte[] plaintext, 
        CancellationToken cancellationToken = default);
}

// 自定义加密结果接口
public interface IEncryptResult
{
    byte[] Ciphertext { get; }
}

// 实现类包装Azure SDK的CryptographyClient
public class KeyVaultCryptoService : IKeyVaultCryptoService
{
    private readonly CryptographyClient _client;

    public KeyVaultCryptoService(CryptographyClient client)
    {
        _client = client;
    }

    public async Task<IEncryptResult> EncryptAsync(
        EncryptionAlgorithm algorithm, 
        byte[] plaintext, 
        CancellationToken cancellationToken = default)
    {
        var sdkResult = await _client.EncryptAsync(algorithm, plaintext, cancellationToken);
        return new EncryptResultAdapter(sdkResult);
    }

    // 适配器类,将SDK的EncryptResult转换为自定义接口
    private class EncryptResultAdapter : IEncryptResult
    {
        private readonly EncryptResult _innerResult;

        public EncryptResultAdapter(EncryptResult innerResult)
        {
            _innerResult = innerResult;
        }

        public byte[] Ciphertext => _innerResult.Ciphertext;
    }
}

测试时直接Mock自定义接口,无需处理Azure SDK的限制:

var mockCryptoService = new Mock<IKeyVaultCryptoService>();
// 自定义测试用的加密结果
var testResult = new Mock<IEncryptResult>();
testResult.Setup(r => r.Ciphertext).Returns(Convert.FromBase64String("测试密文"));

mockCryptoService.Setup(s => s.EncryptAsync(
        It.IsAny<EncryptionAlgorithm>(), 
        It.IsAny<byte[]>(), 
        default))
    .ReturnsAsync(testResult.Object);

// 将Mock实例注入KeyVaultClientWrapper进行测试
var wrapper = new KeyVaultClientWrapper(mockCryptoService.Object);

2. 使用Azurite进行集成测试

如果单元测试的Mock方案过于繁琐,可采用集成测试,使用Azurite(Azure本地模拟器)模拟Key Vault服务,直接调用真实的加密流程,测试结果更贴近生产环境,无需Mock SDK类。

只需在测试前启动Azurite,创建测试用的密钥,然后让CryptographyClient连接到Azurite的端点即可完成测试。


内容的提问来源于stack exchange,提问作者mohanraj

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 18:52:38