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

如何用pytest Patch AWS Secrets Manager的list_secrets返回值?

解决方法

问题根源

你测试代码里patch的是自己创建的secret_client对象,但待测试的list方法会重新调用boto3.client("secretsmanager")生成全新的客户端实例,两个客户端不是同一个对象,所以补丁根本没作用到目标代码上。

正确的补丁方式

方法1:Patch boto3.client返回值,复用修改后的客户端

直接patch boto3.client,让它返回你预先修改好list_secrets方法的客户端,确保待测试代码使用的是同一个实例:

def test_list(self):
    secret_client = boto3.client("secretsmanager")
    secret_client.create_secret(
        Name="test-secret",
        Tags=[{"Key": "id", "Value": "xyz"}],
    )

    secret_client.rotate_secret(
        SecretId="test-secret",
        RotationRules={'AutomaticallyAfterDays': 30},
        RotationLambdaARN=mock_rotation_lambda,
        RotateImmediately=True,
    )

    # 获取原始结果并添加缺失字段
    original_result = secret_client.list_secrets()
    original_result["SecretList"][0]['NextRotationDate'] = datetime(2024, 1, 1, tzinfo=datetime.timezone.utc)

    # 模拟带过滤逻辑的list_secrets方法
    def mock_list_secrets(**kwargs):
        filtered_result = original_result.copy()
        # 适配待测试代码中的name过滤条件
        if kwargs.get("Filters"):
            for filter in kwargs["Filters"]:
                if filter["Key"] == "name" and "test" in filter["Values"]:
                    filtered_result["SecretList"] = [
                        s for s in filtered_result["SecretList"] 
                        if "test" in s["Name"]
                    ]
        return filtered_result

    # 替换客户端的list_secrets方法
    secret_client.list_secrets = mock_list_secrets

    # Patch boto3.client,让待测试代码用这个修改后的客户端
    with patch("boto3.client", return_value=secret_client):
        result = sut.list()
        # 验证结果包含目标字段
        assert "NextRotationDate" in result[0]

方法2:直接Patch SecretsManager客户端的底层方法

通过patch botocore层面的客户端方法,覆盖所有实例的list_secrets行为:

from botocore.client import SecretsManager

def test_list(self):
    secret_client = boto3.client("secretsmanager")
    secret_client.create_secret(
        Name="test-secret",
        Tags=[{"Key": "id", "Value": "xyz"}],
    )

    secret_client.rotate_secret(
        SecretId="test-secret",
        RotationRules={'AutomaticallyAfterDays': 30},
        RotationLambdaARN=mock_rotation_lambda,
        RotateImmediately=True,
    )

    original_result = secret_client.list_secrets()
    original_result["SecretList"][0]['NextRotationDate'] = datetime(2024, 1, 1, tzinfo=datetime.timezone.utc)

    def mock_list_secrets(self, **kwargs):
        result = original_result.copy()
        # 处理待测试代码的过滤条件
        if kwargs.get("Filters"):
            for filter in kwargs["Filters"]:
                if filter["Key"] == "name" and "test" in filter["Values"]:
                    result["SecretList"] = [
                        s for s in result["SecretList"] 
                        if "test" in s["Name"]
                    ]
        return result

    with patch.object(SecretsManager.Client, "list_secrets", side_effect=mock_list_secrets):
        result = sut.list()
        assert "NextRotationDate" in result[0]

关键注意点

  • 必须适配过滤参数:待测试代码传入了name过滤条件,mock方法要对应处理,否则返回的密钥列表会不符合预期。
  • 时区处理:AWS返回的NextRotationDate是带UTC时区的datetime,建议用datetime(2024, 1, 1, tzinfo=datetime.timezone.utc)模拟,避免类型不一致的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 19:15:03