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

Python单元测试mock JSON文件测试do_magic方法报错求解

错误原因

你当前的报错和mock失效问题来自三个核心错误:

  1. mock_open的read_data参数仅接受字符串、字节串类型的输入,你直接传入了Python字典对象。当代码调用文件对象的read()方法时,mock内部逻辑会尝试对read_data调用字符串的join方法,字典没有该方法,直接抛出AttributeError。
  2. builtins.open的mock作用域错误:你在mock open的with代码块内仅做了手动读文件的测试操作,退出with块后mock就自动失效了,后续执行do_magic()时调用的是系统真实的open方法,读取的是本地真实的Science.json文件,你构造的测试数据根本没有进入业务逻辑。
  3. 业务代码里用"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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 12:45:37