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

使用Moto Mock EC2 Filter遇迭代错误,求解决建议

解决Mock EC2资源时的TypeError: 'Mock' object is not iterable问题

原Python类/函数

class A:
  def __init__(aws_profile_name, aws_region, ec2_id):
      self.session = boto3.session.Session(profile_name=aws_profile_name, aws_region)

      self.ec2 = EC2(self.session, aws_region, id=ec2_id)

class EC2:
  def __init__(self, session, aws_region, id):
      self.session = session
      self.region = aws_region
      self.id = id
  
      self.ec2_resource = self.session.resource("ec2", region_name=self.region)
      self.ec2_client = self.session.client("ec2", region_name=self.region)

      self.instance = self.filter_ec2_by_id()

  def filter_ec2_by_id(self):
      return self.filter(
            InstanceIds=[
               self.get_instance_id(),
            ]
        )

  def filter(self, kwargs):
    instances = self.ec2_resource.instances.filter(**kwargs)
    instance_list = [instance for instance in instances]
    return instance_list

测试代码(test.py)

from unittest import mock
import sys
from moto import mock_ec2
import boto3

@mock_ec2
def test_mock_session():
    mock_session_obj = mock.Mock()

    ec2 = boto3.resource("ec2", region_name="us-east-1")
    reservation = client.run_instances(ImageId="ami-1234", MinCount=2, MaxCount=2)
    instance1 = ec2.Instance(reservation["Instances"][0]["InstanceId"])

    ec2 = EC2(mock_session_obj, region="us-east-1", id=instance1)

test_mock_session()

错误信息

instance_list = [instance for instance in instances]
TypeError: 'Mock' object is not iterable

问题根源

你用mock.Mock()创建的mock_session_obj,其resource()方法默认返回Mock对象,而该Mock的instances.filter()返回的仍是不可迭代的Mock,导致遍历时报错。同时原类和测试代码还存在几处语法/逻辑遗漏问题。

解决建议

方案1:正确Mock调用链,返回可迭代对象

手动Mocksession.resource()的返回值,让instances.filter()返回可迭代的模拟实例列表,同时补充未定义的方法:

from unittest import mock
import sys
from moto import mock_ec2
import boto3

# 替换为EC2类所在的实际模块
from your_module import EC2

@mock_ec2
def test_mock_session():
    mock_session_obj = mock.Mock()
    
    # 模拟EC2资源对象
    mock_ec2_resource = mock.Mock()
    # 模拟单个EC2实例
    mock_instance = mock.Mock()
    # 让filter返回包含模拟实例的可迭代列表
    mock_ec2_resource.instances.filter.return_value = [mock_instance]
    # 绑定session.resource的返回值
    mock_session_obj.resource.return_value = mock_ec2_resource
    
    # Mock EC2类中未定义的get_instance_id方法
    with mock.patch.object(EC2, 'get_instance_id', return_value='i-123456'):
        ec2 = EC2(mock_session_obj, aws_region="us-east-1", id='i-123456')
        # 断言返回的实例列表长度正确
        assert len(ec2.instance) == 1

test_mock_session()

方案2:利用moto模拟真实Session(更推荐)

既然已经用moto模拟EC2服务,直接使用moto创建的真实Session传递给EC2类,测试更贴近真实场景:

第一步:修正原类的语法错误

import boto3

class A:
  # 补充self参数,修正Session的region参数名
  def __init__(self, aws_profile_name, aws_region, ec2_id):
      self.session = boto3.session.Session(profile_name=aws_profile_name, region_name=aws_region)
      self.ec2 = EC2(self.session, aws_region, id=ec2_id)

class EC2:
  def __init__(self, session, aws_region, id):
      self.session = session
      self.region = aws_region
      self.id = id
  
      self.ec2_resource = self.session.resource("ec2", region_name=self.region)
      self.ec2_client = self.session.client("ec2", region_name=self.region)
      self.instance = self.filter_ec2_by_id()

  # 补充未定义的get_instance_id方法
  def get_instance_id(self):
      return self.id

  def filter_ec2_by_id(self):
      return self.filter(InstanceIds=[self.get_instance_id()])

  def filter(self, kwargs):
    instances = self.ec2_resource.instances.filter(**kwargs)
    instance_list = [instance for instance in instances]
    return instance_list

第二步:修改测试代码

from moto import mock_ec2
import boto3

# 替换为EC2类所在的实际模块
from your_module import EC2

@mock_ec2
def test_mock_session():
    # 使用moto创建真实Session
    session = boto3.session.Session(region_name="us-east-1")
    ec2_client = session.client("ec2")
    
    # 创建测试用EC2实例
    reservation = ec2_client.run_instances(ImageId="ami-1234", MinCount=2, MaxCount=2)
    instance_id = reservation["Instances"][0]["InstanceId"]
    
    # 初始化EC2类,传递真实Session和实例ID
    ec2 = EC2(session, aws_region="us-east-1", id=instance_id)
    
    # 断言筛选出的实例数量正确
    assert len(ec2.instance) == 1
    # 断言实例ID匹配
    assert ec2.instance[0].id == instance_id

test_mock_session()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 22:01:16