Python单元测试mock JSON文件测试do_magic方法报错求解
错误原因
你当前的报错和mock失效问题来自三个核心错误:
mock_open的read_data参数仅接受字符串、字节串类型的输入,你直接传入了Python字典对象。当代码调用文件对象的read()方法时,mock内部逻辑会尝试对read_data调用字符串的join方法,字典没有该方法,直接抛出AttributeError。builtins.open的mock作用域错误:你在mock open的with代码块内仅做了手动读文件的测试操作,退出with块后mock就自动失效了,后续执行do_magic()时调用的是系统真实的open方法,读取的是本地真实的Science.json文件,你构造的测试数据根本没有进入业务逻辑。- 业务代码里用
"rb"二进制模式打开文件,给mock传内容时需要匹配读取格式,否则json.load解析时会抛类型错误。
正确实现方案
修正后的测试代码如下:
import unittest from unittest.mock import patch, mock_open import json from earth import Earth class TestEarth(unittest.TestCase): @patch('earth.Bar.get_bar') @patch('earth.Foo.get_foo') def test_earth_mung_not_match(self, mock_get_foo, mock_get_bar): # 配置Foo、Bar的mock返回值 mock_get_foo.return_value = "PV" mock_get_bar.return_value = "Science.json" # 构造自定义JSON测试数据,必须序列化为字节串匹配rb读取模式 test_json = {"items": ["PBV"]} mock_file_content = json.dumps(test_json).encode("utf-8") # mock open的作用域必须覆盖do_magic的执行全程 with patch('builtins.open', mock_open(read_data=mock_file_content)) as mock_file: earth_obj = Earth() actual_result = earth_obj.do_magic() # 可选校验:验证文件是否按预期路径、模式被打开 mock_file.assert_called_once_with("Science.json", "rb") # 断言:拼接结果为"PV PBV",和基准值"Raaj hello"不等,返回False self.assertFalse(actual_result) @patch('earth.Bar.get_bar') @patch('earth.Foo.get_foo') def test_earth_mung_match(self, mock_get_foo, mock_get_bar): # 第二个测试场景:构造匹配基准值的输入,验证返回True的分支 mock_get_foo.return_value = "Raaj" mock_get_bar.return_value = "Science.json" test_json = {"items": ["hello"]} mock_file_content = json.dumps(test_json).encode("utf-8") with patch('builtins.open', mock_open(read_data=mock_file_content)): earth_obj = Earth() actual_result = earth_obj.do_magic() self.assertTrue(actual_result) if __name__ == '__main__': unittest.main()
关键注意事项
- 传给
mock_open的read_data是文件被读取时返回的原始内容,和你平时手动读文件拿到的内容格式一致,不能直接传字典、列表这类结构化对象。JSON格式的测试数据需要先用json.dumps()序列化为字符串,再根据文件打开模式决定是否转成字节串。 - 所有依赖mock的业务逻辑调用,必须放在patch对应的上下文管理器(with块)内部,否则mock会被自动回收,替换不了真实方法。
- 多场景测试只需要调整
mock_get_foo的返回值、JSON测试数据的内容,就能生成不同的mung_string值,覆盖所有返回分支。
内容的提问来源于stack exchange,提问作者Raaj
相关产品推荐
相关产品推荐

