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

如何修改脚本用unittest.mock测试open写操作的输出内容?

解决unittest.mock测试文件写入内容的问题

核心思路

用unittest.mock.mock_open模拟文件操作,重点解决三个问题:

  • 给模拟读文件预设内容,避免StopIteration错误
  • 正确关联上下文管理器的返回值,捕获写入句柄的调用记录
  • 完全通过mock验证,无需依赖真实文件

完整示例代码

被测函数(fn)

def fn(file1_path, file2_path, out_path):
    with open(file1_path, 'r') as f1, open(file2_path, 'r') as f2, open(out_path, 'w') as out:
        content1 = f1.read()
        content2 = f2.read()
        out.write(content1 + content2)

测试代码

import unittest
from unittest.mock import mock_open, patch

class TestFn(unittest.TestCase):
    def test_fn_writes_correct_content(self):
        # 定义模拟输入内容与预期输出
        mock_content1 = "Hello from file1\n"
        mock_content2 = "Hello from file2\n"
        expected_output = mock_content1 + mock_content2

        # 配置mock_open:为每次open调用分配对应模拟文件对象
        mock_file = mock_open()
        mock_file.side_effect = [
            mock_open(read_data=mock_content1).return_value,
            mock_open(read_data=mock_content2).return_value,
            mock_open().return_value
        ]

        with patch("builtins.open", mock_file):
            # 调用被测函数
            fn("file1.txt", "file2.txt", "out.txt")

        # 提取所有write调用的内容并拼接
        write_calls = mock_file.return_value.write.call_args_list
        actual_output = ''.join([call[0][0] for call in write_calls])

        # 断言完整输出匹配预期
        self.assertEqual(actual_output, expected_output)

if __name__ == "__main__":
    unittest.main()

关键问题解析

  • 避免StopIteration:通过side_effect为每次open调用分配带预设内容的模拟文件对象,读操作直接返回预设值,不会触发空迭代错误。
  • 捕获write调用:第三次open对应写模式,其mock句柄的write调用会被完整记录,通过call_args_list提取所有写入片段,拼接后即可验证完整内容。
  • 无真实文件依赖:全程在内存中模拟文件操作,不存在文件关闭后无法读取的问题,也不会生成真实文件。

简化写法(针对多文件读取场景)

如果不想用side_effect,也可以直接给上下文返回值绑定读方法:

def test_fn_simplified(self):
    expected_output = "file1 contentfile2 content"
    with patch("builtins.open", mock_open()) as mock_file:
        # 为前两次读文件的上下文对象绑定read返回值
        mock_file.return_value.__enter__.side_effect = [
            type('MockRead1', (), {'read': lambda self: "file1 content"})(),
            type('MockRead2', (), {'read': lambda self: "file2 content"})(),
            mock_file.return_value.__enter__()
        ]
        fn("f1", "f2", "out")
        # 拼接并验证写入内容
        actual = ''.join(call[0][0] for call in mock_file.return_value.write.call_args_list)
        self.assertEqual(actual, expected_output)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 14:36:03