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

如何为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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 02:10:25