Mock对象不可迭代报错:ParserManner类pytest测试问题咨询
解决pytest测试中TypeError: 'Mock' object is not iterable的问题
待测试的Python类
class ParserManner(): def __init__(self, **kwargs): self.file_path = kwargs.get('file_path', None) self.soup = kwargs.get('soup', None) self.observations = [] self.ap_path = kwargs.get('ap_path', 'testy/ap.xml') self.plugin_map_path = kwargs.get('plugin_map_path', 'testy/plugin_map.csv') @classmethod def load(cls, file_name) -> 'ParserManner': file_path = None try: # some code here pass except: raise RuntimeError("Unable to load soup") return ParserManner(file_path=file_path, soup=soup) def parse(self, soup) -> list['Orange']: try: # 此处逻辑会遍历soup或调用其返回可迭代对象的方法 pass except: pass
现有测试代码
步骤1:初始化实例方法
def setup_instance(): instance = ParserManner() instance.ap_path = 'some_path' instance.plugin_map_path = 'some_path' instance.file_path = 'some_path' instance.observations = [] return instance
步骤2:测试方法
def test_open_file_success(): with patch('builtins.open', mock_open(read_data='<assessment-plan></assessment-plan>')) as mock_file: instance = setup_instance() instance.parse(Mock()) mock_file.assert_called_once_with('some_path', 'r')
问题描述
运行上述测试代码时抛出错误:TypeError: 'Mock' object is not iterable
解决方案
错误原因
parse方法内部逻辑会尝试遍历传入的soup对象,或调用soup的某个返回可迭代内容的方法(比如BeautifulSoup的find_all),但默认的Mock()对象没有实现迭代相关的魔法方法,也没有模拟这些方法的返回值,导致触发类型错误。
具体修复方式
方式1:让Mock对象支持迭代
给Mock添加__iter__方法,使其返回一个空迭代器:
def test_open_file_success(): with patch('builtins.open', mock_open(read_data='<assessment-plan></assessment-plan>')) as mock_file: instance = setup_instance() mock_soup = Mock() # 模拟迭代行为,返回空迭代器 mock_soup.__iter__ = Mock(return_value=iter([])) instance.parse(mock_soup) mock_file.assert_called_once_with('some_path', 'r')
方式2:模拟实际soup的方法返回可迭代内容
如果parse方法是通过调用soup.find_all等方法获取可迭代结果,直接模拟对应方法的返回值:
def test_open_file_success(): with patch('builtins.open', mock_open(read_data='<assessment-plan></assessment-plan>')) as mock_file: instance = setup_instance() mock_soup = Mock() # 模拟find_all返回空列表(可迭代) mock_soup.find_all.return_value = [] instance.parse(mock_soup) mock_file.assert_called_once_with('some_path', 'r')
方式3:使用真实的BeautifulSoup实例测试
如果测试场景允许,直接用测试数据创建真实的soup对象,更贴近实际运行逻辑:
from bs4 import BeautifulSoup def test_open_file_success(): with patch('builtins.open', mock_open(read_data='<assessment-plan></assessment-plan>')) as mock_file: instance = setup_instance() # 创建真实的soup实例 test_soup = BeautifulSoup('<assessment-plan></assessment-plan>', 'xml') instance.parse(test_soup) mock_file.assert_called_once_with('some_path', 'r')
内容的提问来源于stack exchange,提问作者Tes
相关产品推荐
相关产品推荐

