如何用Python的mock_open模拟同一文件的读写更新场景
问题分析与解决方案
你的测试代码核心问题是重复patch了同一个builtins.open:第二个@patch会完全覆盖第一个,导致你定义的read_mock根本不会被执行,所有open调用都会走第二个mock,这就是断言失败的原因。
正确的做法是用单个mock_open实例来模拟文件的两次打开(读和写),同时跟踪读写的内容,具体实现如下:
修正后的测试代码
import unittest from unittest.mock import patch, mock_open import json # 替换成你的实际模块名 from your_module import simple_read_write class Example(unittest.TestCase): @patch("builtins.open", new_callable=mock_open, read_data=json.dumps({"change": "old data"})) def test_simple_read_write(self, mock_file): # 执行待测试函数 simple_read_write() # 验证文件被按顺序打开两次:先读再写 mock_file.assert_has_calls([ unittest.mock.call("file", "r"), unittest.mock.call("file", "w") ], any_order=False) # 捕获并验证写入的内容(避免JSON格式差异导致的断言失败) # 拼接所有write调用的内容(json.dump可能分多次写入) written_content = "".join(call.args[0] for call in mock_file().write.call_args_list) # 解析成字典后对比,比直接断言字符串更可靠 written_data = json.loads(written_content) self.assertEqual(written_data, {"change": "some content"})
关键细节说明
单个mock实例覆盖所有调用:
一个mock_open实例会记录所有open调用的参数和顺序,用assert_has_calls可以精准验证两次打开的模式和路径是否正确。避免JSON格式陷阱:
json.dump生成的字符串可能和json.dumps直接生成的有格式差异(比如缩进、空格),所以捕获写入内容后解析成字典再对比,能避免无意义的断言失败。正确获取write调用记录:
mock_file()返回的是模拟的文件对象实例,它的write方法会被json.dump调用,通过call_args_list可以获取所有写入的内容片段并拼接。
内容的提问来源于stack exchange,提问作者Sanjay Nayak
相关产品推荐
相关产品推荐

