如何为moto未实现的EC2 describe_reserved_instances编写单元测试
当moto的mock_ec2未实现describe_reserved_instances时,如何编写单元测试
方案一:直接Mock EC2客户端方法
无需依赖moto的未实现功能,用Python标准库的unittest.mock(或pytest-mock)模拟describe_reserved_instances的返回值,快速完成单元测试,聚焦业务逻辑验证。
基于unittest的示例代码
import unittest from unittest.mock import Mock from your_module import get_reserved_instance # 替换为实际模块名 class TestGetReservedInstance(unittest.TestCase): def test_get_reserved_instance(self): # 构造模拟返回数据 mock_ri_response = { "ReservedInstances": [ { "ReservedInstancesId": "ri-12345678", "InstanceType": "t2.micro", "OfferingClass": "convertible" } ] } # 创建Mock的EC2客户端 mock_ec2_client = Mock() mock_ec2_client.describe_reserved_instances.return_value = mock_ri_response # 调用被测试函数 result = get_reserved_instance(mock_ec2_client) # 验证结果 self.assertEqual(len(result), 1) self.assertEqual(result[0]["OfferingClass"], "convertible") # 验证方法调用参数是否匹配 mock_ec2_client.describe_reserved_instances.assert_called_once_with( Filters=[], OfferingClass="convertible" ) if __name__ == "__main__": unittest.main()
基于pytest的示例代码
from unittest.mock import Mock from your_module import get_reserved_instance def test_get_reserved_instance(): mock_ri_response = { "ReservedInstances": [ {"ReservedInstancesId": "ri-12345678", "OfferingClass": "convertible"} ] } mock_ec2_client = Mock() mock_ec2_client.describe_reserved_instances.return_value = mock_ri_response result = get_reserved_instance(mock_ec2_client) assert len(result) == 1 assert result[0]["OfferingClass"] == "convertible" mock_ec2_client.describe_reserved_instances.assert_called_once_with( Filters=[], OfferingClass="convertible" )
方案二:扩展moto的MockEC2类实现缺失方法
如果需要贴近真实AWS环境的测试(比如结合moto已实现的其他功能),可以扩展moto的MockEC2类,补充describe_reserved_instances的实现。
示例代码
import pytest from moto.ec2.models import MockEC2 from moto import mock_ec2 from your_module import get_reserved_instance import boto3 # 扩展MockEC2类,添加describe_reserved_instances方法 class MockEC2WithRI(MockEC2): def describe_reserved_instances(self, Filters=None, OfferingClass=None, **kwargs): # 模拟真实AWS的返回逻辑 reserved_instances = [] if OfferingClass == "convertible": reserved_instances = [ { "ReservedInstancesId": "ri-87654321", "InstanceType": "t3.small", "OfferingClass": "convertible" } ] return {"ReservedInstances": reserved_instances} @mock_ec2 def test_get_reserved_instance_with_extended_moto(): ec2_client = boto3.client("ec2", region_name="us-east-1") # 替换底层的mock实例为自定义实现 ec2_client._endpoint._instance = MockEC2WithRI() # 调用被测试函数 result = get_reserved_instance(ec2_client) # 验证结果 assert len(result) == 1 assert result[0]["OfferingClass"] == "convertible"
方案对比
- 方案一:实现简单,专注业务逻辑测试,无需关注moto细节,适合纯单元测试场景。
- 方案二:更贴近真实AWS交互,适合需要结合其他moto已实现服务的集成测试,但实现复杂度更高。
内容的提问来源于stack exchange,提问作者Jason LiLy
相关产品推荐
相关产品推荐

