嘲笑 "with open()"
Mocking "with open()"
我正在尝试对从文件中读取行并进行处理的方法进行单元测试。
with open([file_name], 'r') as file_list:
for line in file_list:
# Do stuff
我尝试了其他问题中描述的几种方法,但其中 none 似乎适用于这种情况。我不太明白 python 如何将文件对象用作线上的可迭代对象,它在内部使用 file_list.readlines() ?
这种方式不行:
with mock.patch('[module_name].open') as mocked_open: # also tried with __builtin__ instead of module_name
mocked_open.return_value = 'line1\nline2'
我得到了一个
AttributeError: __exit__
可能是因为 with 语句有这个关闭文件的特殊属性?
此代码使 file_list 成为 MagicMock。我如何在此 MagicMock 上存储数据以对其进行迭代?
with mock.patch("__builtin__.open", mock.mock_open(read_data="data")) as mock_file:
此致
mock_open
的 return 值(直到 Python 3.7.1)不提供有效的 __iter__
方法,这可能使其不适合测试代码遍历打开的文件对象。
相反,我建议重构您的代码以获取已打开的类文件对象。也就是说,而不是
def some_method(file_name):
with open([file_name], 'r') as file_list:
for line in file_list:
# Do stuff
...
some_method(file_name)
写成
def some_method(file_obj):
for line in file_obj:
# Do stuff
...
with open(file_name, 'r') as file_obj:
some_method(file_obj)
这将一个必须执行 IO 的函数变成了一个简单地迭代 any 类文件对象的纯 (r) 函数。要测试它,您不需要模拟 open
或以任何方式访问文件系统;只需创建一个 StringIO
对象用作参数:
def test_it(self):
f = StringIO.StringIO("line1\nline2\n")
some_method(f)
(如果你仍然觉得有必要编写和测试像
这样的包装器
def some_wrapper(file_name):
with open(file_name, 'r') as file_obj:
some_method(file_obj)
请注意,您不需要模拟打开来做任何特别的事情。您单独测试 some_method
,因此测试 some_wrapper
唯一需要做的就是验证 open
的 return 值是否传递给了 some_method
。 open
,在这种情况下,可以是没有特殊行为的普通旧模拟。)
我正在尝试对从文件中读取行并进行处理的方法进行单元测试。
with open([file_name], 'r') as file_list:
for line in file_list:
# Do stuff
我尝试了其他问题中描述的几种方法,但其中 none 似乎适用于这种情况。我不太明白 python 如何将文件对象用作线上的可迭代对象,它在内部使用 file_list.readlines() ?
这种方式不行:
with mock.patch('[module_name].open') as mocked_open: # also tried with __builtin__ instead of module_name
mocked_open.return_value = 'line1\nline2'
我得到了一个
AttributeError: __exit__
可能是因为 with 语句有这个关闭文件的特殊属性?
此代码使 file_list 成为 MagicMock。我如何在此 MagicMock 上存储数据以对其进行迭代?
with mock.patch("__builtin__.open", mock.mock_open(read_data="data")) as mock_file:
此致
mock_open
的 return 值(直到 Python 3.7.1)不提供有效的 __iter__
方法,这可能使其不适合测试代码遍历打开的文件对象。
相反,我建议重构您的代码以获取已打开的类文件对象。也就是说,而不是
def some_method(file_name):
with open([file_name], 'r') as file_list:
for line in file_list:
# Do stuff
...
some_method(file_name)
写成
def some_method(file_obj):
for line in file_obj:
# Do stuff
...
with open(file_name, 'r') as file_obj:
some_method(file_obj)
这将一个必须执行 IO 的函数变成了一个简单地迭代 any 类文件对象的纯 (r) 函数。要测试它,您不需要模拟 open
或以任何方式访问文件系统;只需创建一个 StringIO
对象用作参数:
def test_it(self):
f = StringIO.StringIO("line1\nline2\n")
some_method(f)
(如果你仍然觉得有必要编写和测试像
这样的包装器def some_wrapper(file_name):
with open(file_name, 'r') as file_obj:
some_method(file_obj)
请注意,您不需要模拟打开来做任何特别的事情。您单独测试 some_method
,因此测试 some_wrapper
唯一需要做的就是验证 open
的 return 值是否传递给了 some_method
。 open
,在这种情况下,可以是没有特殊行为的普通旧模拟。)