如何模拟List类型全局变量?模拟结果不符合预期的问题排查
解决Mock全局列表变量的问题
我来帮你搞定这个mock全局列表的问题!你现在遇到的核心问题是错误地把全局变量当成了可调用的方法来处理,导致mock没有生效,反而返回了MagicMock对象。
为什么你的写法不对?
你用了mock_url_list.return_value.url.return_value = [['a','b'],['c','d']],但first_main.url是一个全局列表变量,不是函数/方法,根本不存在return_value这一说——return_value是用来mock可调用对象(比如函数、类方法)的返回值的,直接用在变量上完全不生效,所以mock对象还是原来的MagicMock实例。
两种正确的解决方法
方法1:直接替换成目标列表(最简单)
如果你不需要在测试过程中动态修改这个列表,直接用patch的new参数把url替换成你想要的列表就行,连mock参数都不用处理:
@mock.patch('first_main.url', new=[['a','b'],['c','d']]) def test_method_b(self): response = method_b() print(response)
这样method_b里访问的url就是你指定的列表,打印出来完全符合预期。
方法2:让Mock对象模拟列表行为(适合动态修改场景)
如果需要在测试中动态调整列表内容,可以修改mock对象的行为,让它表现得像一个真实的列表:
@mock.patch('first_main.url') def test_method_b(self, mock_url_list): # 让mock对象支持迭代(比如for循环、打印时的展示) target_list = [['a','b'],['c','d']] mock_url_list.__iter__.return_value = iter(target_list) # 如果method_b里用到了列表索引访问(比如url[0]),还要加上这行 mock_url_list.__getitem__.side_effect = lambda idx: target_list[idx] response = method_b() print(response)
这样mock对象就会模拟真实列表的迭代和索引访问行为,method_b里打印出来的就是你想要的内容。
补充提示
如果你的method_b里还会对url进行修改(比如append),那可以在mock对象上模拟append方法:
mock_url_list.append = MagicMock()
不过根据你的场景,只是打印并返回True,前面的两种方法已经足够解决问题啦。
内容的提问来源于stack exchange,提问作者PySaad
相关产品推荐
相关产品推荐

