如何为Python AWS CDK VPC from_lookup编写pytest单元测试
问题背景
当CDK栈通过Vpc.from_lookup方法获取现有VPC资源时,运行单元测试必须配置真实有效的AWS凭证才能完成资源查询,这种依赖真实云环境的方式在单元测试场景下既不实用也不符合测试隔离的预期。
核心诉求
编写不依赖真实AWS凭证、不发起真实云API请求的pytest用例,完成栈逻辑的单元校验。
待测试示例代码
测试目标栈文件为ec2_stack.py,代码如下:
# Deps from aws_cdk import ( Stack, aws_ec2 as _ec2, ) from constructs import Construct class Ec2Test(Stack): """ An EC2 test """ def __init__( self, scope: Construct, construct_id: str, **kwargs, ) -> None: super().__init__(scope, construct_id, **kwargs) self.vpc_id = self.node.try_get_context("vpc_id") self.inst_type = self.node.try_get_context("inst_type") self.base_ami_id = self.node.try_get_context("base_ami_id") self._vpc = _ec2.Vpc.from_lookup( scope=self, id="my-vpc", vpc_id=self.vpc_id, ) self._machine_image = _ec2.MachineImage.generic_linux( {"ap-southeast-2": self.base_ami_id} ) self.__create_instance() def __create_instance(self): """ Create EC2 instance resource """ _ec2.Instance( self, "ec2", instance_type=_ec2.InstanceType(self.inst_type), vpc=self._vpc, machine_image=self._machine_image, )
实现方案
单元测试的核心原则是隔离外部依赖,CDK本身提供了本地模板断言能力,不需要真实调用AWS API,通过mock拦截lookup请求即可实现无凭证测试:
- 测试阶段拦截
Vpc.from_lookup调用,替换为本地构造的VPC属性对象,完全跳过真实云API请求和凭证校验流程 - 测试全程不需要配置AWS凭证、不需要联网,所有逻辑在本地内存中完成
- 用CDK自带的模板断言工具校验生成的CloudFormation资源配置是否符合预期,不需要执行真实部署
具体实现步骤
- 先安装测试所需依赖:
pip install pytest aws-cdk-lib constructs
- 在测试目录下创建测试文件
test_ec2_stack.py,代码如下:
import aws_cdk as core import aws_cdk.assertions as assertions from aws_cdk import aws_ec2 as _ec2 from ec2_stack import Ec2Test def test_ec2_stack_resource_config(): # 初始化测试用App实例,传入测试所需的context参数 app = core.App(context={ "vpc_id": "vpc-0123456789abcdef0", "inst_type": "t3.micro", "base_ami_id": "ami-0123456789abcdef0" }) # 核心mock逻辑:替换from_lookup方法,返回本地构造的VPC对象 # 该操作会拦截所有VPC lookup请求,不会发起任何真实AWS API调用 _ec2.Vpc.from_lookup = lambda scope, id, vpc_id: _ec2.Vpc.from_vpc_attributes( scope=scope, id=id, vpc_id=vpc_id, availability_zones=["ap-southeast-2a", "ap-southeast-2b", "ap-southeast-2c"], public_subnet_ids=["subnet-001", "subnet-002", "subnet-003"], private_subnet_ids=["subnet-101", "subnet-102", "subnet-103"] ) # 初始化待测试的栈实例 stack = Ec2Test(app, "test-ec2-stack") # 生成CloudFormation模板断言对象 template = assertions.Template.from_stack(stack) # 校验EC2实例创建数量符合预期 template.resource_count_is("AWS::EC2::Instance", 1) # 校验实例类型、镜像ID配置正确 template.has_resource_properties("AWS::EC2::Instance", { "InstanceType": "t3.micro", "ImageId": "ami-0123456789abcdef0" })
运行说明
- 直接执行
pytest test_ec2_stack.py -v即可启动测试,全程无外网请求、无凭证校验 - 该方案通过monkey patch替换了
from_lookup的默认实现,完全绕开了CDK默认的云环境查询逻辑 - 如果需要覆盖不同VPC场景的测试,只需要调整mock返回的VPC属性(比如子网数量、可用区配置)即可,不需要修改业务栈代码
注意:单元测试不要依赖真实AWS凭证和云环境,否则会导致测试运行速度慢、结果不稳定,还可能产生非预期的云资源调用成本。
内容的提问来源于stack exchange,提问作者Efren
相关产品推荐
相关产品推荐

