如何模拟 with 语句中使用的 open(使用 Python 中的 Mock 框架)?
如何使用 unittest.mock
< 测试以下代码/a>:
def testme(filepath):
with open(filepath) as f:
return f.read()
How do I test the following code with unittest.mock
:
def testme(filepath):
with open(filepath) as f:
return f.read()
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(11)
Python 3
补丁
builtins.open
并使用mock_open
,它是模拟
框架。补丁
用作上下文管理器 返回用于替换修补后的对象:如果您想使用
patch
作为装饰器,请使用mock_open()
的结果作为patch<的
new=
参数/code> 可能有点奇怪。相反,请使用patch
的new_callable=
参数,并记住patch
不使用的每个额外参数都将传递给new_callable
函数,如patch文档
:
请记住,在这种情况下,
patch
会将模拟对象作为参数传递给您的测试函数。Python 2
您需要修补
__builtin__.open
而不是builtins.open
并且mock
不是unittest
的一部分,您需要pip install
并单独导入它:Python 3
Patch
builtins.open
and usemock_open
, which is part of themock
framework.patch
used as a context manager returns the object used to replace the patched one:If you want to use
patch
as a decorator, usingmock_open()
's result as thenew=
argument topatch
can be a little bit weird. Instead, usepatch
'snew_callable=
argument and remember that every extra argument thatpatch
doesn't use will be passed to thenew_callable
function, as described in thepatch
documentation:Remember that in this case
patch
will pass the mocked object as an argument to your test function.Python 2
You need to patch
__builtin__.open
instead ofbuiltins.open
andmock
is not part ofunittest
, you need topip install
and import it separately:做到这一点的方法在mock 0.7.0中发生了变化,它最终支持模拟python协议方法(魔术方法),特别是使用MagicMock:
http://www.voidspace.org.uk/python/mock/magicmock.html
作为上下文管理器模拟打开的示例(来自模拟文档中的示例页面):
The way to do this has changed in mock 0.7.0 which finally supports mocking the python protocol methods (magic methods), particularly using the MagicMock:
http://www.voidspace.org.uk/python/mock/magicmock.html
An example of mocking open as a context manager (from the examples page in the mock documentation):
使用最新版本的mock,您可以使用真正有用的mock_open 帮助器:
With the latest versions of mock, you can use the really useful mock_open helper:
要使用 mock_open 来创建简单文件
读取()
(原始的mock_open代码段已在此页面上给出更适合写入):请注意mock_open 的文档,这是专门针对
read()
的,因此不适用于常见模式,例如for line in f
。使用 python 2.6.6 / 模拟 1.0.1
To use mock_open for a simple file
read()
(the original mock_open snippet already given on this page is geared more for write):Note as per docs for mock_open, this is specifically for
read()
, so won't work with common patterns likefor line in f
, for example.Uses python 2.6.6 / mock 1.0.1
如果您不再需要任何文件,您可以装饰测试方法:
If you don't need any file further, you can decorate the test method:
最上面的答案很有用,但我对其进行了一些扩展。
如果您想根据传递给
open()
的参数设置文件对象的值(as f
中的f
),这里有一个实现方法:基本上,
open()
将返回一个对象,而with
将在该对象上调用__enter__()
。为了正确模拟,我们必须模拟
open()
以返回一个模拟对象。然后,该模拟对象应该模拟对其的 __enter__() 调用(MagicMock
将为我们执行此操作)以返回我们想要的模拟数据/文件对象(因此mm.__enter__.return_value
)。通过上述方式使用 2 个模拟执行此操作,我们可以捕获传递给open()
的参数,并将它们传递给我们的do_something_with_data
方法。我将整个模拟文件作为字符串传递给
open()
,我的do_something_with_data
看起来像这样:这会将字符串转换为列表,以便您可以像您一样执行以下操作与普通文件:
The top answer is useful but I expanded on it a bit.
If you want to set the value of your file object (the
f
inas f
) based on the arguments passed toopen()
here's one way to do it:Basically,
open()
will return an object andwith
will call__enter__()
on that object.To mock properly, we must mock
open()
to return a mock object. That mock object should then mock the__enter__()
call on it (MagicMock
will do this for us) to return the mock data/file object we want (hencemm.__enter__.return_value
). Doing this with 2 mocks the way above allows us to capture the arguments passed toopen()
and pass them to ourdo_something_with_data
method.I passed an entire mock file as a string to
open()
and mydo_something_with_data
looked like this:This transforms the string into a list so you can do the following as you would with a normal file:
我可能有点晚了,但是当我在另一个模块中调用
open
而无需创建新文件时,这对我有用。test.py
MyObj.py
通过将
__builtin__
模块内的open
函数修补到我的mock_open()
,我可以模拟写入文件,而无需创建一个。注意:如果您使用的模块使用 cython,或者您的程序以任何方式依赖于 cython,则需要导入 cython 的
__builtin__
模块,方法是在文件顶部包含import __builtin__
。如果您使用 cython,您将无法模拟通用__builtin__
。I might be a bit late to the game, but this worked for me when calling
open
in another module without having to create a new file.test.py
MyObj.py
By patching the
open
function inside the__builtin__
module to mymock_open()
, I can mock writing to a file without creating one.Note: If you are using a module that uses cython, or your program depends on cython in any way, you will need to import cython's
__builtin__
module by includingimport __builtin__
at the top of your file. You will not be able to mock the universal__builtin__
if you are using cython.使用unittest修补内置的open()函数:
这适用于读取json配置的补丁。
模拟对象是 open() 函数返回的 io.TextIOWrapper 对象
To patch the built-in open() function with unittest:
This worked for a patch to read a json config.
The mocked object is the io.TextIOWrapper object returned by the open() function
在我的例子中,我使用的是 pytest,好消息是在 Python 3 中,unittest 库也可以毫无问题地导入和使用。
这是我的方法。首先,我创建一个包含可重用 pytest 固定装置的
conftest.py
文件:我决定将
read_data
作为属性,以便更加 Pythonic。它可以在测试函数中与open()
需要返回的任何数据一起分配。在我的测试文件中,名称类似于
test_it_works.py
,我有一个以下测试用例来确认预期的功能:查看要点 此处。
I'm using
pytest
in my case, and the good news is that in Python 3 theunittest
library can also be imported and used without issue.Here is my approach. First, I create a
conftest.py
file with reusable pytest fixture(s):Where I decided to make the
read_data
as a property, in order to be more pythonic. It can be assigned in a test function with whatever data thatopen()
needs to return.In my test file, named something like
test_it_works.py
, I have a following test case to confirm intended functionality:Check out the gist here.
源自 github 代码片段,用于修补 python 中的读写功能。
源链接位于此处
Sourced from a github snippet to patch read and write functionality in python.
The source link is over here
带有断言的简单@patch
如果您想使用@patch。 open() 在处理程序内部被调用并被读取。
SIMPLE @patch with assert
If you're wanting to use @patch. The open() is called inside the handler and is read.