【发布时间】:2026-01-11 10:20:03
【问题描述】:
我正在尝试编写一个单元测试模拟来打开一个文件并将其传递给一个函数,该函数使用它来将 JSON 对象转储到其中。如何创建一个模拟打开文件句柄行为但使用相似属性的假 IO 对象,特别是 .name?
我已经阅读了这里的大量答案,所有答案都以各种方式解决了这个问题。我试过模拟修补builtins.open,我试过模拟修补在我的模块内被调用的open,但我一直遇到的主要错误是当我尝试访问假IO对象的.name属性时,我得到一个属性错误:
AttributeError: 'CallbackStream' object has no attribute 'name'
所以这是一个简单的函数,它以 JSON 格式将字典写入磁盘并获取打开的文件句柄:
def generate(data, json_file):
# data is a dict
logging.info(f"Writing out spec file to {json_file.name}")
json.dump(data, json_file)
这是我尝试进行单元测试的内容:
@patch("builtins.open", new_callable=mock_open())
def test_generate_json_returns_zero(self, mock_open):
mocked_file = mock_open()
mocked_file.name = "FakeFileName"
data = {'stuff': 'stuff2'}
generate(data, json_file=mocked_file)
但是,这会产生上面的 AttributeError,我不能使用 json_file.name,因为它不作为属性存在。我认为明确设置它会起作用,但它没有。
我可以通过 `tempfile.TemporaryFile: 使用临时文件来绕过这个问题:
def test_generate_json_returns_zero(self, mock_open):
data = {'stuff': 'stuff2'}
t = TemporaryFile("w")
generate(data, json_file=t)
但这并不能解决 实际 问题,即我无法弄清楚如何模拟文件句柄,因此我实际上不需要在磁盘上创建真实文件.
我无法通过.name 不是有效属性。如何模拟文件对象,以便我可以实际使用 IO 对象的 .name 属性并仍然对其伪造 json.dump()?
【问题讨论】:
标签: python-3.x mocking python-unittest