用Python模拟文件打开

27

我试图模仿文件打开,所有的例子都显示我需要

@patch('open', create=True) 

但我一直都在遇到这个问题

Need a valid target to patch. You supplied: 'open'

我知道 patch 需要 open 的完整点路径(full dotted path),但我不知道它是什么。事实上,我甚至不确定那是否是问题所在。


2
  1. 从您发布的内容中,我们无法告诉您路径应该是什么,或者是否存在问题。请提供一个最小化且完整可运行的示例(MCVE)。
  2. 您知道针对此类情况有专门的 mock_open 吗?具体请参考 Python官方文档
- jonrsharpe
2个回答

34

在Python 3中,您应该使用装饰器

@mock.patch("builtins.open", create=True)

或作为上下文管理器

with mock.patch('builtins.open', mock.mock_open(read_data=some_data)) as m:
    ...

这是简单、直接明了、易于理解和优雅的内容。谢谢。 - lallolu
如果您只想在尝试打开特定文件时使其起作用,该怎么办? - Roelant

33

您需要包含一个模块名称;如果您正在脚本中进行测试,则模块的名称为__main__

@patch('__main__.open')
否则,请使用包含您正在测试的代码的模块的名称:
@patch('module_under_test.open')

因此,任何使用内置的open()函数的代码都将找到已修补的全局变量。

请注意,mock模块附带一个mock_open()实用程序,它可以让您构建带有文件数据的适当的open()调用:

@patch('__main__.open', mock_open(read_data='foo\nbar\nbaz\n'))

进一步的问题:这样的模拟(具有指定的返回值)是否可以作为上下文管理器(在with语句中)使用? - 0xc0de
@0xc0de:是的,我提供的文档包含了open()with语句中使用以及使用mock_open()进行补丁的示例。 - Martijn Pieters
是的,我后来在这里询问之后看到了。谢谢。 - 0xc0de
进一步的问题:如果打开了两个不同的文件,并且您想为两个文件都提供“read_data”内容,那么该如何进行修补? - Roelant
1
@Roelant:两个都打补丁。patch()可以使用模拟对象替换目标,因此首先创建模拟对象,然后使用patch()将两个目标替换为同一个对象。或者,只需创建两个模拟对象,因为这样可能会有好处(您可以以不同的方式配置模拟对象)。 - Martijn Pieters

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接